[loj6519]魔力环
根据Burnside引理,枚举旋转的步数$k$,求不动点的数目
令$d=\gcd(n,k)$,这个问题其实可以等价于填$\frac{n}{d}$个长度为$d$的环(因此很明显$\frac{n}{d}|m$是必要条件)
对于$d$相同的$k$是等价的,因此不妨枚举$d$,则$k$的数量即为$\sum_{i=1}^{\frac{n}{d}}[\gcd(i,\frac{n}{d})=1]=\varphi(\frac{n}{d})$
记$n'=d,m'=\frac{md}{n}$,对于这个子问题,由于其旋转所得是不同的,因此枚举首尾的黑点数量之和,即$ans=\sum_{i=0}^{k}i\cdot f(n'-i-2,m'-i)$,其中$f(n,m)$表示这个子问题在序列上的答案
(这里要特判,当$m'\le k$时答案显然为$c(n',m')$)
考虑$f(n,m)$的计算,可以看作将$m$个黑点分为至多$n-m+1$份(可以为空且不超过$k$)的方案数
令$n'=n-m+1$,容斥存在$i$份超过$k$,将他们都减去$k$,那么这$n'$份就没有限制,再根据插板法即可得到$f(n,m)=\sum_{0\le i\le n',i(k+1)\le m}(-1)^{i}\cdot c(n',i)\cdot c(m-i(k+1)+n'-1,n'-1)$
时间复杂度:$o(\sum_{d|n}k\cdot \frac{\frac{md}{n}}{k})=o(\sigma_{1}(n))\le o(n\ln n)$(先枚举$d$,再枚举$i$,最后计算$f$),可以通过
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 100005 4 #define mod 998244353 5 int n,m,k,ans,fac[N],inv[N],p[N],vis[N],phi[N]; 6 int c(int n,int m){ 7 return 1LL*fac[n]*inv[m]%mod*inv[n-m]%mod; 8 } 9 int f(int n,int m){ 10 int nn=n-m+1,ans=0; 11 for(int i=0;(i<=nn)&&(i*(k+1)<=m);i++){ 12 int s=1LL*c(nn,i)*c(m-i*(k+1)+nn-1,nn-1)%mod; 13 if (i&1)ans=(ans+mod-s)%mod; 14 else ans=(ans+s)%mod; 15 } 16 return ans; 17 } 18 int calc(int n,int m){ 19 if (m<=k)return c(n,m); 20 int ans=0; 21 for(int i=0;i<=k;i++) 22 if ((n-i-2>=0)&&(m>=i))ans=(ans+1LL*(i+1)*f(n-i-2,m-i))%mod; 23 return ans; 24 } 25 int main(){ 26 scanf("%d%d%d",&n,&m,&k); 27 fac[0]=inv[0]=inv[1]=phi[1]=1; 28 for(int i=1;i<N-4;i++)fac[i]=1LL*fac[i-1]*i%mod; 29 for(int i=2;i<N-4;i++)inv[i]=1LL*(mod-mod/i)*inv[mod%i]%mod; 30 for(int i=1;i<N-4;i++)inv[i]=1LL*inv[i-1]*inv[i]%mod; 31 for(int i=2;i<N-4;i++){ 32 if (!vis[i]){ 33 p[++p[0]]=i; 34 phi[i]=i-1; 35 } 36 for(int j=1;(j<=p[0])&&(i*p[j]<N-4);j++){ 37 vis[i*p[j]]=1; 38 if (i%p[j])phi[i*p[j]]=phi[i]*phi[p[j]]; 39 else{ 40 phi[i*p[j]]=phi[i]*p[j]; 41 break; 42 } 43 } 44 } 45 for(int i=1;i*i<=n;i++){ 46 if ((n%i==0)&&(m%(n/i)==0))ans=(ans+1LL*phi[n/i]*calc(i,m/(n/i)))%mod; 47 if ((i*i!=n)&&(n%i==0)&&(m%i==0))ans=(ans+1LL*phi[i]*calc(n/i,m/i))%mod; 48 } 49 printf("%lld",1LL*ans*fac[n-1]%mod*inv[n]%mod); 50 }