TopCoder 11351 TheCowDivOne

vj

考虑生成函数,答案可以写成\([x^0y^k]\prod_{i=0}^{n-1}(1+x^iy)\pmod {x^n-1}\)

\(=\sum_i[x^{in}y^k]\prod_{j=0}^{n-1}(1+x^jy)\)

\(=\sum_i[x^iy^k]\prod_{j=0}^{n-1}(1+x^jy)[n|i]\)

这里单位根反演,原式

\(=\frac{1}{n}[y^k]\sum_{i=0}^{n-1}\prod_{j=0}^{n-1}(1+\omega_n^{ij}y)\)

然后对于每个\(i\),后面那坨多项式的形式只和\(\gcd(i,n)\)有关,这里改为枚举这个\(\gcd\)的值,原式

\(=\frac{1}{n}\sum_{d|n}[y^k](\prod_{j=0}^{n/d-1}(1+\omega_n^{jd}y))^d\sum_{j=1}^{n}[\gcd(j,n)=d]\)

\(=\frac{1}{n}\sum_{d|n}[y^k](\prod_{j=0}^{d-1}(1+\omega_d^jy))^{n/d}\sum_{j=1}^{n}[\gcd(j,n)=\frac{n}{d}]\)

\(=\frac{1}{n}\sum_{d|n}\varphi(d)[y^k](1+(-1)^{d+1}y^d)^{n/d}\)

然后二项式定理,求出对应组合数即可知道对应的\(y^k\)的系数.这里的\(d\)也要满足\(d|k\)

btw,下面这个代码不是忘topcoder上交的(

#include<bits/stdc++.h>
#define LL long long
#define db double

using namespace std;
const int N=2000+10,mod=1e9+7;
int rd()
{
    int x=0,w=1;char ch=0;
    while(ch<'0'||ch>'9'){if(ch=='-') w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+(ch^48);ch=getchar();}
    return x*w;
}
void ad(int &x,int y){x+=y,x-=x>=mod?mod:0;}
int fpow(int a,int b){int an=1;while(b){if(b&1) an=1ll*an*a%mod;a=1ll*a*a%mod,b>>=1;}return an;}
int ginv(int a){return fpow(a,mod-2);}
int n,k,inv[N],d[N],td,phi[N],p[N][2],tt;
void dfs(int o,int s,int ph)
{
    if(o>tt){d[++td]=s,phi[td]=ph;return;}
    int ft=1;
    for(int i=0;i<=p[o][1];++i)
	dfs(o+1,s,ph),s*=p[o][0],ph*=p[o][0]-ft,ft=0;
}
int C(int a,int b)
{
    if(b<0||a<b) return 0;
    int an=1;
    for(int i=1;i<=b;++i) an=1ll*an*(a-i+1)%mod*inv[i]%mod;
    return an;
}

int main()
{
    inv[0]=inv[1]=1;
    for(int i=2;i<=N-5;++i) inv[i]=(mod-1ll*mod/i*inv[mod%i]%mod)%mod;
    while(~scanf("%d%d",&n,&k))
    {
    	tt=0;
    	int x=n,sqt=sqrt(n);
    	for(int i=2;i<=sqt;++i)
    	    if(x%i==0)
    	    {
    	    	p[++tt][0]=i,p[tt][1]=0;
    	    	while(x%i==0) x/=i,++p[tt][1];
    	    }
    	if(x>1) p[++tt][0]=x,p[tt][1]=1;
    	td=0,dfs(1,1,1);
    	int ans=0;
    	for(int i=1;i<=td;++i)
    	{
    	    int x=d[i];
    	    if(k%x) continue;
    	    int dx=1ll*phi[i]*C(n/x,k/x)%mod;
    	    ad(ans,((x^1)&(k/x)&1)?mod-dx:dx);
    	}
    	ans=1ll*ans*ginv(n)%mod;
    	printf("%d\n",ans);
    }
    return 0;
} 
posted @ 2020-04-01 08:42  ✡smy✡  阅读(298)  评论(0编辑  收藏  举报