CF896D Nephren Runs a Cinema
看了番,速來補(bǔ)題。(Nephren 沒死,可以說是萬幸了。)
雖然不知道為什么有黑?感覺是擴(kuò)展Lucas板子?
題相當(dāng)于是計(jì)數(shù)一個(gè)ABC序列,使得序列長度為\(n\),且對于每一個(gè)前綴,A的數(shù)量大于B的數(shù)量。A的總數(shù)減B的總數(shù)在\([l,r]\)內(nèi)。
那么我們可以枚舉\(C\)的數(shù)量,然后接下來就是一堆很典的格路計(jì)數(shù)。總之現(xiàn)在我們只用計(jì)算\(O(n)\)次\(\binom{x}{y}\bmod P\)(\(x\le 1e5,y\le 1e5,P\le 2e9\))
然后我們上擴(kuò)展lucas板子,不過稍微變一下形式。
CRT后,將\(\binom{n}{m}\bmod P^k\)直接拆成\(\Large \frac{\frac{n!}{P^x}}{\frac{m!}{P^y}\frac{(n-m)!}{P^z}} P^{x-y-z}\bmod P^k\),其中\(\frac{n!}{P^x}\)表示為\(n!\)除去所有\(P\)因子的值
計(jì)算\(\large f(n)=\frac{n!}{P^x}\)時(shí),
因?yàn)?span id="w0obha2h00" class="math inline">\(f(n)=f(\lfloor \frac{n}{P}\rfloor )\prod_{i=1,i\nmid P}^{n}i \bmod P^k\),我們可以預(yù)處理出\(\prod_{i=1,i\nmid P}^{n}i \bmod P^k\)。
這樣時(shí)間就是顯然的\(O(n\log^2 n)\)了。
原神代碼:
#include<bits/stdc++.h>
using namespace std;
using ll=long long;
const int N=2e5+5,M=1005;
int P,Pk;
bool vis[N];
int prime[N],pcnt;
inline ll ksm(ll a,ll b,ll p){
ll res=1;
while(b){
if(b&1)res=res*a%p;
a=a*a%p,b>>=1;
}
return res;
}
void prew(){
for(int i=2;i<N;i++){
if(!vis[i]){
vis[i]=1;
prime[++pcnt]=i;
}
for(int j=1;i*prime[j]<N&&j<=pcnt;j++){
int x=i*prime[j];
vis[x]=1;
if(i%prime[j]==0)continue;
}
}
}
void exgcd(ll a,ll b,ll &x,ll &y){
if(!b)return x=1,y=0,void();
exgcd(b,a%b,y,x);
y-=a/b*x;
}
inline ll ginv(ll a,ll ps){
a%=ps;
ll x,y;
exgcd(a,ps,x,y);
return (x%ps+ps)%ps;
}
ll fac[24][N];
int cnt;
int s1[N],s2[N];
int cur;
ll res[N];
inline int g(int x){
if(!x)return 0;
return x/P+g(x/P);
}
inline ll f(int x){
if(x==0)return 1;
return f(x/P)*fac[cur][x]%Pk;
}
inline ll solve(int n,int m){
return ksm(P,g(n)-g(m)-g(n-m),Pk)*f(n)%Pk*ginv(f(n-m),Pk)%Pk*ginv(f(m),Pk)%Pk;
}
int p;
inline ll C(int n,int m){
if(m<0||n<m)return 0;
for(int i=1;i<=cnt;i++){
cur=i;P=s1[i],Pk=s2[i];
res[i]=solve(n,m);
}
ll ans=0;
for(int i=1;i<=cnt;i++){
Pk=s2[i];
ans+=1ll*res[i]*(p/Pk)%p*ginv(p/Pk,Pk)%p;
}
return ans%p;
}
int n,l,r;
int main(){
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
prew();
cin>>n>>p>>l>>r;
int kp=p;
for(int i=1;i<=pcnt;i++){
int x=prime[i];
if(kp%x==0){
++cnt;
s1[cnt]=x,s2[cnt]=x,kp/=x;
while(kp%x==0)kp/=x,s2[cnt]*=x;
}
if(kp==1)break;
}
if(kp^1){
++cnt;
s1[cnt]=kp,s2[cnt]=kp;
}
for(int i=1;i<=cnt;i++){
fac[i][0]=1;
for(int j=1;j<=n;j++){
if(j%s1[i])fac[i][j]=fac[i][j-1]*j%s2[i];
else fac[i][j]=fac[i][j-1];
}
}
ll ans=0;
for(int i=0;i<=n;i++){
int pl=(i+l+1)/2,pr=(i+r)/2;
pl=max(pl,0),pr=min(pr,i);
pl=max(pl,(i+1)/2);
if(pl>pr)continue;
ll res=0;
res+=C(i,pl)-C(i,pr+1)+p;
res%=p;
ans+=res*C(n,i)%p;
}
cout<<ans%p<<"\n";
return 0;
}

浙公網(wǎng)安備 33010602011771號