P3121 [USACO15FEB]Censoring G
阿新 • • 發佈:2021-11-08
不知道該怎麼做?
匹配,開個棧並記錄。刪掉一個單詞以後就從上一個單詞的位置繼續匹配。
為什麼匹配過程不跳 fail?因為題目保證沒有單詞是另外一個單詞的字串。
#include<cstdio> #include<iostream> #include<cstring> #include<iomanip> #include<cmath> #include<stack> #include<algorithm> using namespace std; #define int long long template<class T>inline void read(T &x) { x=0;register char c=getchar();register bool f=0; while(!isdigit(c))f^=c=='-',c=getchar(); while(isdigit(c))x=(x<<3)+(x<<1)+(c^48),c=getchar(); if(f)x=-x; } template<class T>inline void print(T x) { if(x<0)putchar('-'),x=-x; if(x>9)print(x/10); putchar('0'+x%10); } int t; int n; int r; int m; int cnt; long long prime[10000001]; int maxn=10000005; int vis[10000005]; int fz[10000005]; void prim(){ for(int i=2;i<=maxn;++i){ if(!vis[i]){ prime[++cnt]=i; } for(int j=1;j<=cnt&&prime[j]*i<=maxn;++j){ vis[i*prime[j]]=1; if(i%prime[j]==0){ break; } } } } int qk(int bas,int m,int p){ long long ans=1; while(m){ if(m&1){ ans=(ans*1ll*bas)%p; } bas*=bas; bas%=p; m>>=1; } return ans; } int fac[10000007]; int cop[10000007]; int fm[10000007]; signed main(){ prim(); read(t);read(r); fac[0]=1; for(int i=1;i<=maxn;++i){ if(i!=r) fac[i]=fac[i-1]*1ll*i%r; else fac[i]=fac[i-1]; } fz[1]=(prime[1]-1)%r;cop[1]=prime[1]; for(int i=2;i<=cnt;++i){ fz[i]=(fz[i-1])*1ll*(prime[i]-1)%r; cop[i]=prime[i]; } for(int i=1;i<=cnt;++i){ if(cop[i]!=r) cop[i]=qk(cop[i],r-2,r); } for(int i=2;i<=cnt;++i){ if(cop[i]!=r) cop[i]=cop[i]*1ll*cop[i-1]%r; else cop[i]=cop[i-1]; } while(t--){ read(n);read(m); if(m<r&&r<=n){ puts("0"); continue; } int pl=upper_bound(prime+1,prime+1+cnt,m)-prime-1; if(pl<1){ printf("%lld\n",fac[n]); }else{ printf("%lld\n",fac[n]*1ll*fz[pl]%r*1ll*cop[pl]%r); } } return 0; }