P4456题解
题意
称没有连续 1 的 01 序列为交错序列。定义一个 01 序列的权值为 0 和 1 的个数,
思路
枚举 1 的个数可知答案为
发现
现在问题在于如何
首先设函数
现在我们需要计算
很遗憾,被我卡掉了。
我们发现题面里并没有给出
怎么办呢?
我们考虑把数记为
我们可以提前预处理出
所以时间复杂度为
但是这种做法全身都是瓶颈,所以常数可能偏大,写的时候需要注意常数,不开 O2 可能过不去。如果开了还过不去可以试试取模优化。
代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e7+5;
int n,mod,M,a,b,pwa[N],pwb[N],p[N],pcnt,ans;
int pw(int x,int p){
int res=1;
for(;p;p>>=1,x=x*x%mod) if(p&1) res=res*x%mod;
return res;
}
struct Int{
int x,k;//x*m^k
Int operator *(const Int&re)const{
return (Int){x*re.x%mod,k+re.k};
}
Int inv(){
return (Int){pw(x,mod-2),-k};
}
int toi(){
assert(k>=0);//如果k<0,容易证明此时这个数不存在。
if(k>0) return 0;
return x;
}
}F[N],Inv[N];
Int get(int x){
int k=0;
while(x%mod==0) x/=mod,k++;
return (Int){x%mod,k};
}
int C(int x,int y){
if(x<y||y<0) return 0;
return (F[x]*Inv[y]*Inv[x-y]).toi();
}
bool s[N];
void sh(){//线性筛
pwa[0]=a==0,pwb[0]=b==0;
pwa[1]=1,pwb[1]=1;
for(int i=2;i<=n;i++){
if(!s[i]){//质数处的计算
pwa[i]=pw(i,a);
pwb[i]=pw(i,b);
p[++pcnt]=i;
}
for(int j=1;j<=pcnt&&i*p[j]<=n;j++){//和数处的计算
pwa[i*p[j]]=pwa[i]*pwa[p[j]]%mod;
pwb[i*p[j]]=pwb[i]*pwb[p[j]]%mod;
s[i*p[j]]=1;
if(i%p[j]==0) break;
}
}
}
signed main(){
cin>>n>>a>>b>>mod;
sh();
F[0]=get(1);
M=min(mod-1,n+2);
for(int i=1;i<=M;i++) F[i]=F[i-1]*get(i);
Inv[M]=F[M].inv();
for(int i=M;i>=1;i--) Inv[i-1]=Inv[i]*get(i);
for(int i=0;i<=n-i+1;i++) ans=(ans+C(n-i+1,i)*pwb[i]%mod*pwa[n-i])%mod;
cout<<ans;
return 0;
}