今天模拟赛考得没有感觉,感觉数学专题没用到数学......
T1 young
做这个题,本来以为摇摆兵可以早一点切掉,然后让他帮帮我来着
结果他就比我早了一分钟,并且我们两个同时写出了答案相同的错误代码呃呃
好难的亚子
该说的题解都说了,我这里给出p的求法
哎呀算了算了直接看代码吧
code
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
int read(){
int s=0,t=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')t=-1;ch=getchar();}
while(isdigit(ch)){s=s*10+ch-'0';ch=getchar();}
return s*t;
}
const int mod=258280327;
const int N=51;
const int M=9;
int ksm(int x,int y){
int ret=1;
while(y){
if(y&1)ret=ret*x%mod;
x=x*x%mod;y>>=1;
}return ret;
}
int n,m,ans;
int f[N][M],g[N][N][M],p[N][N][M][1<<M];
int jc[N],inv[N],pw2[(N+1)*M];
int C(int x,int y){return jc[x]*inv[y]%mod*inv[x-y]%mod;}
int P(int s,int t,int m,int k){
if(!m)return 1;
if(!s||!t)return pw2[(s+t)*m];
if(!k)return pw2[(s+t)*m];
if(p[s][t][m][k]!=-1)return p[s][t][m][k];
if((k>>m-1)&1)return p[s][t][m][k]=P(s,t,m-1,k^(1<<(m-1)))*2%mod;
int ret=0;
fo(i,0,s)fo(j,0,t){
int res=C(s,i)*C(t,j)%mod;
res=res*P(i,j,m-1,k)%mod*P(s-i,t-j,m-1,k)%mod;
if((i&&j)||(s-i&&t-j))ret=(ret+res)%mod;
}
ret=(ret+2*P(s,t,m-1,0))%mod;
return p[s][t][m][k]=ret;
}
int G(int s,int t,int m){
if(!s||!t||!m)return 0;
if(g[s][t][m]!=-1)return g[s][t][m];
int ret=0;
fo(k,1,(1<<m)-1)ret=(ret+P(s,t,m,k))%mod;
return g[s][t][m]=ret;
}
int F(int n,int m){
if(!m||n<=1)return 0;
if(f[n][m]!=-1)return f[n][m];
int ret=0;//cout<<"SB"<<endl;
fo(i,0,n){
int res=0;
if(i)res=(res+pw2[(n-i)*(m-1)]*F(i,m-1))%mod;
if(n-i)res=(res+pw2[i*(m-1)]*F(n-i,m-1))%mod;
if(i&&(n-i))res=(res+pw2[(n+1)*(m-1)]+G(i,n-i,m-1))%mod;
ret=(ret+res*C(n,i))%mod;
}
return f[n][m]=ret;
}
signed main(){
n=read();m=read();
memset(f,-1,sizeof(f));
memset(g,-1,sizeof(g));
memset(p,-1,sizeof(p));
pw2[0]=1;fo(i,1,(n+1)*m)pw2[i]=pw2[i-1]*2%mod;
jc[0]=1;fo(i,1,n)jc[i]=jc[i-1]*i%mod;
inv[0]=1;inv[n]=ksm(jc[n],mod-2);
fu(i,n-1,1)inv[i]=inv[i+1]*(i+1)%mod;
ans=F(n,m)*ksm(pw2[n*m],mod-2)%mod;
// cout<<F(n,m)<<" "<<pw2[n*m]<<endl;
// cout<<G(2,2,2)<<endl;
// cout<<P(3,3,3,1)<<endl;
//1 1 2 1 :
// ans=24ll*ksm(16,mod-2)%mod;
printf("%lld",ans);
}
T2 Simple
设\(f(n)\)为\(n\)位钦定数的个数
答案为\(\sum\limits_{i=1}^{n}i^2f(i)\)
这个东西其实是个莫比乌斯反演
我们直接化简它,得到
\[\sum\limits_{d=1}^{n}d*\mu(d)\sum\limits_{i=1}^{\left\lfloor\frac{n}{d} \right\rfloor}i*10^i \]我们发现后面这个咋也不能杜教筛,但是前面那个却可以,于是调换个顺序
\[\sum\limits_{i=1}^{n}i*10^i\sum\limits_{d=1}^{\left\lfloor\frac{n}{i} \right\rfloor}d*\mu(d) \]后面这个直接卷上一个\(id\)就能杜教筛了
前面那个有通项公式,直接\(OEIS\)
其实乘一个\(10\)然后两个一消就完事了,被七百信一眼切了,我和摇摆兵玩了一个小时没玩明白
code
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
int read(){
int s=0,t=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')t=-1;ch=getchar();}
while(isdigit(ch)){s=s*10+ch-'0';ch=getchar();}
return s*t;
}
const int mod=258280327;
const int N=1e7+5;
int ksm(int x,int y){
int ret=1;
while(y){
if(y&1)ret=ret*x%mod;
x=x*x%mod;y>>=1;
}return ret;
}
int n,ans;
signed p[N],cnt,R=1e7;
bool vis[N];
int ss[N],iv,i2;
void init(){
ss[1]=1;
fo(i,2,R){
if(!vis[i])p[++cnt]=i,ss[i]=-1;
for(int j=1;j<=cnt&&i*p[j]<=R;j++){
vis[i*p[j]]=true;
if(i%p[j]==0){ss[i*p[j]]=0;break;}
else ss[i*p[j]]=-ss[i];
}
}
fo(i,1,R)ss[i]=(1ll*ss[i-1]+1ll*i*ss[i]%mod+mod)%mod;
}
int f(int x){return ((9*x-1)%mod*ksm(10,x)%mod+1+mod)%mod*10%mod*iv%mod;}
unordered_map<int,int> mp;
int t(int x){x%=mod;return x*(x+1)%mod*i2%mod;}
int S(int x){
if(x<=R)return ss[x];
if(mp.find(x)!=mp.end())return mp[x];
int ret=1;
for(int l=2,r;l<=x;l=r+1){
r=x/(x/l);
ret=(ret-(t(r)-t(l-1)+mod)*S(x/l)%mod+mod)%mod;
}return mp[x]=ret;
}
signed main(){
n=read();init();iv=ksm(81,mod-2);
i2=ksm(2,mod-2);
for(int l=1,r;l<=n;l=r+1){
r=n/(n/l);
ans=(ans+(f(r)-f(l-1)+mod)*S(n/l))%mod;
}
printf("%lld",ans);
return 0;
}
T3 mate
组合数取模嘛
能直接做的直接做,能\(CRT\)的就\(CRT\),再不济就分解质因数,到点了就输出0
于是乎就切了
正解是线段树维护质因子,因为最后的式子只有一个会变化,所以我们直接用线段树单点修,全局查就行了
code
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
int read(){
int s=0,t=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')t=-1;ch=getchar();}
while(isdigit(ch)){s=s*10+ch-'0';ch=getchar();}
return s*t;
}
const int N=1e6+5;
int n,mod,xpos,ypos;
int p[N],cnt,R=1e6,buc[N],bmo[N];
bool vis[N];
int mo[N],cmo,an[N],ans;
void init(){
fo(i,2,R){
if(!vis[i])p[++cnt]=i;
for(int j=1;j<=cnt&&i*p[j]<=R;j++){
vis[i*p[j]]=true;
if(i%p[j]==0)continue;
}
}
}
int jc[15][N],inv[15][N];
int w(int x,int y,int i){return x>=y?jc[i][x]*inv[i][y]%mo[i]*inv[i][x-y]%mo[i]:0;}
int C(int x,int y,int i){if(y==0)return 1;return C(x/mo[i],y/mo[i],i)*w(x%mo[i],y%mo[i],i)%mo[i];}
int ksm(int x,int y,int mod){
int ret=1;
while(y){
if(y&1)ret=ret*x%mod;
x=x*x%mod;y>>=1;
}return ret;
}
void spj_init(){
fo(i,1,cmo){
int mn=min(n,mo[i]-1);
jc[i][0]=1;fo(j,1,mn)jc[i][j]=jc[i][j-1]*j%mo[i];
inv[i][0]=1;inv[i][mn]=ksm(jc[i][mn],mo[i]-2,mo[i]);
fu(j,mn-1,1)inv[i][j]=inv[i][j+1]*(j+1)%mo[i];
}
}
void spj1(){
spj_init();ans=0;
fo(i,xpos,n-ypos){
if((i+xpos)&1)continue;
ans=(ans+C(n,i,1)*C(i,(xpos+i)>>1,1)%mo[1]*C(n-i,(n-i+ypos)>>1,1))%mo[1];
}
printf("%lld",ans);
}
int exgcd(int a,int b,int &x,int &y){
if(!b)return x=1,y=0,a;
int g=exgcd(b,a%b,x,y),t=x;
x=y;y=t-a/b*y;return g;
}
void spj2(){
spj_init();ans=0;
int sum=1;
fo(j,1,cmo){
fo(i,xpos,n-ypos){
if((i+xpos)&1)continue;
an[j]=(an[j]+C(n,i,j)*C(i,(xpos+i)>>1,j)%mo[j]*C(n-i,(n-i+ypos)>>1,j))%mo[j];
}sum*=mo[j];
}
fo(i,1,cmo){
int m=sum/mo[i],x,y;
exgcd(mo[i],m,x,y);
ans=(ans+y%sum*m%sum*an[i])%sum;
}
ans=(ans+sum)%sum;
printf("%lld",ans);
}
void CC(int x,int y){
fo(i,1,cnt){
if(p[i]>x)break;
int now=x;
while(now)buc[i]+=now/p[i],now/=p[i];
}
fo(i,1,cnt){
if(p[i]>y)break;
int now=y;
while(now)buc[i]-=now/p[i],now/=p[i];
}
fo(i,1,cnt){
if(p[i]>x-y)break;
int now=x-y;
while(now)buc[i]-=now/p[i],now/=p[i];
}
}
signed main(){
n=read();mod=read();init();
xpos=abs(read());ypos=abs(read());
if(n<xpos+ypos||((n+xpos+ypos)&1)||mod==1){printf("0");return 0;}
int fl=0,tmp=mod;
for(int i=1;p[i]*p[i]<=mod;i++){
if(mod%p[i]==0)mod/=p[i],fl=max(fl,2ll),mo[++cmo]=p[i];
while(mod%p[i]==0)mod/=p[i],fl=max(fl,3ll);
}
if(mod>1)fl=max(fl,1ll),mo[++cmo]=mod;
if(fl!=1&&n>90000){printf("0");return 0;}
if(fl==1){spj1();return 0;}
if(fl==2){spj2();return 0;}
mod=tmp;
fo(i,xpos,n-ypos){
if((xpos+i)&1)continue;
int res=1;
CC(n,i);CC(i,(xpos+i)>>1);CC(n-i,(n-i+ypos)>>1);
fo(i,1,cnt)res=res*ksm(p[i],buc[i],mod)%mod,buc[i]=0;
ans=(ans+res)%mod;
}
printf("%lld",ans);
return 0;
}