gmoj 6084. 【GDOI2019模拟2019.3.25】礼物

题目

https://gmoj.net/senior/#main/show/6084

题目大意

你要在一个长度为 n n n 的环中选择 m m m 个点,把它们染成金色,要求没有连续的超过 k k k 个点被染成金色,求有多少个旋转后各不相同的染完色的环。


题解

首先,若 f x , y f_{x,y} fx,y 表示将一个长度为 x x x 的环中的 y y y 个点变成金色,最长的连续金色段长度小于等于 k k k 的方案数。由 Pόlya定理
a n s = ∑ d ∣ gcd ⁡ ( n , m ) f ( n d , m d ) φ ( d ) n ans=\frac{\sum_{d|\gcd{(n,m)}} f\left(\frac{n}{d},\frac{m}{d}\right)\varphi(d)}{n} ans=ndgcd(n,m)f(dn,dm)φ(d)
f f f 写成生成函数的形式:
F a , b ( x ) = ( ∑ i = 0 k x i ) a − b − 1 [ ∑ i = 0 k ( i + 1 ) x i ] F_{a,b}(x)=\left(\sum_{i=0}^k x^i \right)^{a-b-1} \left[\sum_{i=0}^k (i+1)x^i \right] Fa,b(x)=(i=0kxi)ab1[i=0k(i+1)xi]
上式考虑的是在 a − b a-b ab 个不染色点之间插入 b b b 个金色点的方案。后面的部分表示在 n n n 号点和 1 1 1 号点之间的间隙中插入的方案,前面的部分表示在剩下的 a − b − 1 a-b-1 ab1 个间隙中插入的方案。

那么
a n s = ∑ d ∣ gcd ⁡ ( n , m ) [ x m d ] F n d , m d ( x ) ⋅ φ ( d ) n ans=\frac{\sum_{d|\gcd{(n,m)}} \left[x^{\frac{m}{d}}\right]F_{\frac{n}{d},\frac{m}{d}}(x)\cdot \varphi(d)}{n} ans=ndgcd(n,m)[xdm]Fdn,dm(x)φ(d)

现在考虑怎么求 F F F ,首先是怎么把后面那坨 [ ∑ i = 0 k ( i + 1 ) x i ] \left[\sum_{i=0}^k (i+1)x^i \right] [i=0k(i+1)xi] 化掉。

G k ( x ) = ∑ i = 0 k ( i + 1 ) x i G_k(x)=\sum_{i=0}^k (i+1)x^i Gk(x)=i=0k(i+1)xi ,发现
G k ( x ) + ( k + 2 ) x k + 1 = G k + 1 ( x ) = G k ( x ) x + ∑ i = 0 k + 1 x i G ( x ) = 1 + ( k + 1 ) x k + 2 − ( k + 2 ) x k + 1 ( x − 1 ) 2 \begin{aligned} G_k(x)+(k+2)x^{k+1}&=G_{k+1}(x)=G_k(x)x+\sum_{i=0}^{k+1} x^i\\ G(x)&=\frac{1+(k+1)x^{k+2}-(k+2)x^{k+1}}{(x-1)^2} \end{aligned} Gk(x)+(k+2)xk+1G(x)=Gk+1(x)=Gk(x)x+i=0k+1xi=(x1)21+(k+1)xk+2(k+2)xk+1

H = 1 + ( k + 1 ) x k + 2 − ( k + 2 ) x k + 1 H=1+(k+1)x^{k+2}-(k+2)x^{k+1} H=1+(k+1)xk+2(k+2)xk+1 ,那么
F a , b ( x ) = ( ∑ i = 0 k x i ) a − b − 1 [ ∑ i = 0 k ( i + 1 ) x i ] = ( x k + 1 − 1 ) a − b − 1 ( x − 1 ) a − b − 1 ⋅ H ( x − 1 ) 2 等比数列求和 = ( 1 − x k + 1 ) a − b − 1 ( 1 − x ) a − b + 1 ⋅ H = ( 1 − x k + 1 ) a − b − 1 ( 1 − x ) − ( a − b + 1 ) H = [ ∑ i = 0 + ∞ ( a − b − 1 i ) ( − 1 ) i x ( k + 1 ) i ] [ ∑ i = 0 + ∞ ( a − b + i i ) x i ] H 广义二项式定理 \begin{aligned} F_{a,b}(x)&=\left(\sum_{i=0}^k x^i \right)^{a-b-1} \left[\sum_{i=0}^k (i+1)x^i \right]\\ &=\frac{\left(x^{k+1}-1\right)^{a-b-1}}{(x-1)^{a-b-1}}\cdot\frac{H}{(x-1)^2} &\text{等比数列求和} \\ &=\frac{\left(1-x^{k+1} \right)^{a-b-1} }{(1-x)^{a-b+1} } \cdot H\\ &=\left(1-x^{k+1} \right)^{a-b-1} (1-x)^{-(a-b+1)}H\\ &=\left[\sum_{i=0}^{+\infty} \binom{a-b-1}{i} (-1)^i x^{(k+1)i} \right]\left[\sum_{i=0}^{+\infty}\binom{a-b+i}{i}x^i \right]H &\text{广义二项式定理} \end{aligned} Fa,b(x)=(i=0kxi)ab1[i=0k(i+1)xi]=(x1)ab1(xk+11)ab1(x1)2H=(1x)ab+1(1xk+1)ab1H=(1xk+1)ab1(1x)(ab+1)H=[i=0+(iab1)(1)ix(k+1)i][i=0+(iab+i)xi]H等比数列求和广义二项式定理
也就是
F a , b ( x ) = [ ∑ i = 0 + ∞ ( a − b − 1 i ) ( − 1 ) i x ( k + 1 ) i ] [ ∑ j = 0 + ∞ ( a − b + j j ) x j ] [ 1 + ( k + 1 ) x k + 2 − ( k + 2 ) x k + 1 ] F_{a,b}(x)=\left[\sum_{i=0}^{+\infty} \binom{a-b-1}{i} (-1)^i x^{(k+1)i} \right]\\\left[\sum_{j=0}^{+\infty}\binom{a-b+j}{j}x^j \right]\left[1+(k+1)x^{k+2}-(k+2)x^{k+1} \right] Fa,b(x)=[i=0+(iab1)(1)ix(k+1)i][j=0+(jab+j)xj][1+(k+1)xk+2(k+2)xk+1]
把最后那个中括号展开之后,可以得到三个互不干扰的式子。发现对于每个式子,只要知道 i i i ,就可以得到 j j j

那么就可以求出 [ x b ] F a , b ( x ) \left[x^b\right]F_{a,b}(x) [xb]Fa,b(x) 了。令
S 1 = ∑ i = 0 ⌊ b k + 1 ⌋ ( − 1 ) i ( a − b − 1 i ) ( a − i ( k + 1 ) b − i ( k + 1 ) ) , S 2 = ( k + 2 ) ∑ i = 0 ⌊ b − k − 1 k + 1 ⌋ ( − 1 ) i ( a − b − 1 i ) ( a − k − 1 − i ( k + 1 ) b − k − 1 − i ( k + 1 ) ) , S 3 = ( k + 1 ) ∑ i = 0 ⌊ b − k − 2 k + 1 ⌋ ( − 1 ) i ( a − b − 1 i ) ( a − k − 2 − i ( k + 1 ) b − k − 2 − i ( k + 1 ) ) \begin{aligned} S_1 &=\sum_{i=0}^{\left\lfloor\frac{b}{k+1} \right\rfloor} (-1)^i \binom{a-b-1}{i}\binom{a-i(k+1)}{b-i(k+1)},\\ S_2 &=(k+2)\sum_{i=0}^{\left\lfloor\frac{b-k-1}{k+1} \right\rfloor} (-1)^i \binom{a-b-1}{i}\binom{a-k-1-i(k+1)}{b-k-1-i(k+1)},\\ S_3 &=(k+1)\sum_{i=0}^{\left\lfloor\frac{b-k-2}{k+1} \right\rfloor} (-1)^i \binom{a-b-1}{i}\binom{a-k-2-i(k+1)}{b-k-2-i(k+1)} \end{aligned} S1S2S3=i=0k+1b(1)i(iab1)(bi(k+1)ai(k+1)),=(k+2)i=0k+1bk1(1)i(iab1)(bk1i(k+1)ak1i(k+1)),=(k+1)i=0k+1bk2(1)i(iab1)(bk2i(k+1)ak2i(k+1))
那么 [ x b ] F a , b ( x ) = S 1 − S 2 + S 3 \left[x^b\right]F_{a,b}(x)=S_1-S_2+S_3 [xb]Fa,b(x)=S1S2+S3


#include<cstdio>
using namespace std;
#define fo(i,l,r) for(i=l;i<=r;++i)
#define M 1000005
#define N 2000005
const int P=998244353;
int fac[N],ifac[N],inv[N],phi[M],pri[M];
bool tag[M];
inline int get_gcd(int x,int y)
{
	int r=x%y;
	while(r) x=y,y=r,r=x%y;
	return y;
}
inline int C(int x,int y)
{
	return 1LL*fac[x]*ifac[y]%P*ifac[x-y]%P;
}
inline void add(int &x,int y){x+=y;if(x>=P) x-=P;}
int main()
{
	freopen("gift.in","r",stdin);
	freopen("gift.out","w",stdout);
	register int i,j,d;
	int T,n,m,k,a,b,gcd,lim,s1,s2,s3,sum,ans,now,s=0;
	phi[1]=1;
	fo(i,2,1000000)
	{
		if(!tag[i]) pri[++s]=i,phi[i]=i-1;
		fo(j,1,s)
		{
			if(i*pri[j]>1000000) break;
			tag[i*pri[j]]=1;
			if(i%pri[j]==0){phi[i*pri[j]]=phi[i]*pri[j];break;}
			phi[i*pri[j]]=phi[i]*(pri[j]-1);
		}
	}
	fac[0]=1;fo(i,1,2000000) fac[i]=1LL*fac[i-1]*i%P;
	inv[1]=1;fo(i,2,2000000) inv[i]=1LL*inv[P%i]*(P-P/i)%P;
	ifac[0]=1;fo(i,1,2000000) ifac[i]=1LL*ifac[i-1]*inv[i]%P;
	scanf("%d",&T);
	while(T--)
	{
		scanf("%d%d%d",&n,&m,&k);
		if(m==0){puts("1");continue;}
		ans=0,gcd=get_gcd(n,m);
		fo(d,1,gcd) if(gcd%d==0)
		{
			a=n/d,b=m/d;
			if(a-b==0) continue;
			s1=s2=s3=sum=0;
			lim=b/(k+1),j=b;
			fo(i,0,lim)
			{
				now=1LL*C(a-b-1,i)*C(a-b+j,j)%P;
				add(s1,i&1?P-now:now);
				j-=k+1;
			}
			add(sum,s1);
			if(b>=k+1)
			{
				--lim,j=b-k-1;
				fo(i,0,lim)
				{
					now=1LL*C(a-b-1,i)*C(a-b+j,j)%P;
					add(s2,i&1?now:P-now);
					j-=k+1;
				}
				sum=(sum+1LL*(k+2)*s2)%P;
				if(b>=k+2)
				{
					lim=(b-k-2)/(k+1),j=b-k-2;
					fo(i,0,lim)
					{
						now=1LL*C(a-b-1,i)*C(a-b+j,j)%P;
						add(s3,i&1?P-now:now);
						j-=k+1;
					}
					sum=(sum+1LL*(k+1)*s3)%P;
				}
			}
			ans=(ans+1LL*sum*phi[d])%P;
		}
		printf("%lld\n",1LL*ans*inv[n]%P);
	}
	return 0;
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值