[集训队作业2018]uoj 450 复读机 - 组合计数

题目大意:群里有 k 个不同的复读机。为了庆祝平安夜的到来,在接下来的 n 秒内,它们每秒钟都会选出一位优秀的复读机进行复读。非常滑稽的是,一个复读机只有总共复读了 d 的倍数次才会感到快乐。问有多少种不同的安排方式使得所有的复读机都感到快乐。模数19491001.
题解:以d=3为例,设a,b,c是三个三次单位根,那么答案就是 n ! [ x n ] ( e a x + e b x + e c x 3 ) k n![x^n]\left(\frac{e^{ax}+e^{bx}+e^{cx}}3\right)^k ,二项式定理展开算一下即可。

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define Rep(i,v) rep(i,0,(int)v.size()-1)
#define lint long long
#define p 19491001
#define g 7
#define ull unsigned lint
#define db long double
#define pb push_back
#define mp make_pair
#define fir first
#define sec second
#define gc getchar()
#define debug(x) cerr<<#x<<"="<<x
#define sp <<" "
#define ln <<endl
using namespace std;
typedef pair<int,int> pii;
typedef set<int>::iterator sit;
inline int inn()
{
	int x,ch;while((ch=gc)<'0'||ch>'9');
	x=ch^'0';while((ch=gc)>='0'&&ch<='9')
		x=(x<<1)+(x<<3)+(ch^'0');return x;
}
const int N=500010;int fac[N],facinv[N];
inline int fast_pow(int x,int k,int ans=1) { for(;k;k>>=1,x=(lint)x*x%p) (k&1)?ans=(lint)ans*x%p:0;return ans; }
inline int prelude(int n)
{
	rep(i,fac[0]=1,n) fac[i]=(lint)fac[i-1]*i%p;
	facinv[n]=fast_pow(fac[n],p-2);
	for(int i=n-1;i>=0;i--) facinv[i]=(i+1ll)*facinv[i+1]%p;
	return 0;
}
inline int C(int n,int m) { return (lint)fac[n]*facinv[m]%p*facinv[n-m]%p; }
namespace subtask1{
	inline int solve_d1(int n,int k) { return !printf("%d\n",fast_pow(k,n)); }
}
namespace subtask2{
	inline int solve_d2(int n,int k)
	{
		int ans=0;
		rep(i,0,k)
		{
			int t=2*i-k;if(t<0) t+=p;
			ans=(ans+(lint)C(k,i)*fast_pow(t,n))%p;
		}
		ans=(lint)ans*fast_pow(fast_pow(2,k),p-2)%p;
		return !printf("%d\n",ans);
	}
}
namespace subtask3{
	inline int solve_d3(int n,int k)
	{
		int w3=fast_pow(g,(p-1)/3),a=1,b=w3,c=(lint)w3*w3%p,ans=0;
		rep(i,0,k)
		{
			int s=0,t;
			rep(j,0,k-i)
				t=((lint)a*i+(lint)b*j%p+(lint)c*(k-i-j))%p,
				s=(s+(lint)C(k-i,j)*fast_pow(t,n))%p;
			ans=(ans+(lint)C(k,i)*s)%p;
		}
		ans=(lint)ans*fast_pow(fast_pow(3,k),p-2)%p;
		return !printf("%d\n",ans);
	}
}
int main()
{
	int n=inn(),k=inn(),d=inn();prelude(k);
	if(n%d!=0) return !printf("0\n");
	if(d==1) return subtask1::solve_d1(n,k);
	if(d==2) return subtask2::solve_d2(n,k);
	if(d==3) return subtask3::solve_d3(n,k);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/Mys_C_K/article/details/88086680