BZOJ1547: 周末晚會
阿新 • • 發佈:2019-02-12
string tps 1的個數 uri typedef limit amp spa %d
BZOJ1547: 周末晚會
https://lydsy.com/JudgeOnline/problem.php?id=1547
分析:
- 對於一個串旋轉若幹次會回到本身,旋轉次數即是同構個數,這個東西和最小整除周期有關。
- 設\(f_i\)表示有多少個串的最小整除周期是\(i\),\(g_i=\sum\limits_{j|i}f_j,f_i=\sum\limits_{j|i}g_j\mu(i/j)\)。
- 那麽答案就是\(\sum\limits_{i|n}\frac{f_i}{i}\)。
- 當\(n\le K\)時,\(g_i=2^i\), 否則,考慮求一個\(h_i\)表示長度為\(i\)重復出現次數小於等於\(K\)
- 考慮到有用的\(f,g\)一共約數個數個,時間復雜度為\(O(n+\sigma(n)^2)\)。
代碼:
#include <cstdio> #include <cstring> #include <algorithm> #include <cstdlib> using namespace std; #define mod 100000007 #define N 2050 #define M 2050 typedef long long ll; int n,K; ll f[N],g[N]; int pri[M],cnt,mu[M]; bool vis[M]; int w[N],tot,mi[M],h[M],sum[M],sum2[M]; void ins(int x) { w[++tot]=x; } ll qp(ll x,ll y) { ll re=1; for(;y;y>>=1,x=x*x%mod) if(y&1) re=re*x%mod; return re; } void sieve() { int i,j; mu[1]=1; for(i=2;i<=n;i++) { if(!vis[i]) { pri[++cnt]=i; mu[i]=-1; } for(j=1;j<=cnt&&i*pri[j]<=n;j++) { vis[i*pri[j]]=1; if(i%pri[j]==0) { mu[i*pri[j]]=0; break; } mu[i*pri[j]]=-mu[i]; } } } int main() { int T; scanf("%d",&T); while(T--) { scanf("%d%d",&n,&K); cnt=0; if(n<=K) { memset(f,0,sizeof(f)); int i,j; sieve(); for(mi[0]=i=1;i<=n;i++) mi[i]=mi[i-1]*2%mod; for(i=1;i<=n;i++) for(j=i;j<=n;j+=i) { f[j]=(f[j]+mi[i]*mu[j/i])%mod; } int ans=0; for(i=1;i<=n;i++) if(n%i==0) ans=(ans+f[i]*qp(i,mod-2))%mod; printf("%d\n",(ans%mod+mod)%mod); continue; }else { memset(h,0,sizeof(h)); memset(f,0,sizeof(f)); memset(h,0,sizeof(h)); tot=0; int i,j; for(i=1;i*i<=n;i++) { if(n%i==0) { ins(i); if(n/i!=i) ins(n/i); } } sieve(); for(mi[0]=i=1;i<=n;i++) mi[i]=mi[i-1]*2%mod; h[0]=1; sum[0]=1; for(i=1;i<=K;i++) h[i]=mi[i],sum[i]=(sum[i-1]+h[i])%mod; for(i=K+1;i<=n;i++) { if(i>K+1) h[i]=(sum[i-1]-sum[i-K-2]+mod)%mod; else h[i]=sum[i-1]; sum[i]=(sum[i-1]+h[i])%mod; } for(i=0;i<=n;i++) sum2[i]=(sum2[i-1]+ll(n-i)*h[i])%mod; for(i=1;i<=tot;i++) { if(w[i]<=K+1) g[i]=mi[w[i]]-1; else { /*for(j=0;j<=K;j++) { g[i]=(g[i]+ll(j+1)*h[w[i]-j-2])%mod; }*/ ll ss2,ss1; if(w[i]>K+2) ss2=sum2[w[i]-2]-sum2[w[i]-K-3],ss1=sum[w[i]-2]-sum[w[i]-K-3]; else ss2=sum2[w[i]-2],ss1=sum[w[i]-2]; g[i]=((ss2-ll(n-w[i]+1)*ss1)%mod+mod)%mod; //g[i]=((sum2[w[i]-2]-sum2[w[i]-K-2]-ll(n-w[i]+1)*(sum[w[i]-2]-sum[w[i]-K-2]))%mod+mod)%mod; } } for(i=1;i<=tot;i++) { for(j=1;j<=tot;j++) if(w[j]%w[i]==0) { f[j]=(f[j]+g[i]*mu[w[j]/w[i]])%mod; } } int ans=0; for(i=1;i<=tot;i++) ans=(ans+ll(f[i])*qp(w[i],mod-2))%mod; printf("%d\n",(ans%mod+mod)%mod); continue; } } }
BZOJ1547: 周末晚會