51Nod 1317 相似字串對
阿新 • • 發佈:2020-08-20
前兩天上課講的題,還是比較simple的
考慮對於相似字串的操作,不難發現兩個字串相似當且僅當它們迴圈同構
因此我們可以列舉迴圈節的長度\(i\),那麼和他迴圈同構的串的個數顯然就是\(i\)
接下來就是計算迴圈節長為\(i\)的方案數了,我們不難想到可以在最短迴圈節長度處統計答案,因此直接大力容斥即可
複雜度\()O(\pi(n)^2)\)
#include<cstdio> #include<algorithm> #define RI register int #define CI const int& using namespace std; const int N=100005,mod=1e9+7; int n,k,d[N],cnt,f[N],ans; inline int quick_pow(int x,int p,int mul=1) { for (;p;p>>=1,x=1LL*x*x%mod) if (p&1) mul=1LL*mul*x%mod; return mul; } inline void inc(int& x,CI y) { if ((x+=y)>=mod) x-=mod; } inline void dec(int& x,CI y) { if ((x-=y)<0) x+=mod; } int main() { RI i,j; for (scanf("%d%d",&n,&k),i=1;i*i<=n;++i) if (n%i==0) d[++cnt]=i,(n!=i*i)&&(d[++cnt]=n/i); for (sort(d+1,d+cnt+1),i=1;i<=cnt;++i) for (f[i]=quick_pow(k,d[i]),j=1;j<i;++j) if (d[i]%d[j]==0) dec(f[i],f[j]); for (i=1;i<=cnt;++i) inc(ans,1LL*f[i]*d[i]%mod); return printf("%d",ans),0; }