UOJ450 集训队作业2018 复读机

Problem

UOJ

Solution

注意到 d ≤ 3 d\leq 3 d3 d = 2 d=2 d=2 k ≤ 5 × 1 0 5 k\leq 5\times 10^5 k5×105 d = 3 d=3 d=3 k ≤ 1000 k\leq 1000 k1000,明示分类讨论= =

对于 d = 1 d=1 d=1,答案显然是 k n k^n kn


其他的,我们可以考虑用指数型生成函数,对于每个复读机的生成函数都一样,如果我们设生成函数为 f ( x ) f(x) f(x),那么答案其实就是 f k ( x ) [ n ] f^k(x)[n] fk(x)[n]

对于 d = 2 d=2 d=2 { 1 , 0 , 1 , 0 , ⋯   } \{1,0,1,0,\cdots\} {1,0,1,0,},它的指数型生成函数是 f ( x ) = e x + e − x 2 f(x)=\frac {e^x+e^{-x}} 2 f(x)=2ex+ex,那么

f k ( x ) = 1 2 k ( e x + e − x ) k = 1 2 k ∑ i = 0 k ( k i ) e i x e ( i − k ) x = 1 2 k ∑ i = 0 k ( k i ) e ( 2 i − k ) x f^k(x)=\frac 1 {2^k} (e^x+e^{-x})^k=\frac 1 {2^k}\sum_{i=0}^k\binom k i e^{ix}e^{(i-k)x}=\frac 1 {2^k}\sum_{i=0}^k\binom k i e^{(2i-k)x} fk(x)=2k1(ex+ex)k=2k1i=0k(ik)eixe(ik)x=2k1i=0k(ik)e(2ik)x

( e a x ) [ n ] = a n (e^{ax})[n]=a^n (eax)[n]=an,因此直接暴力枚举 i i i +快速幂即可做到 O ( k log ⁡ n ) O(k\log n) O(klogn)


对于 d = 3 d=3 d=3 { 1 , 0 , 0 , 1 , 0 , 0 , 1 , ⋯   } \{1,0,0,1,0,0,1,\cdots\} {1,0,0,1,0,0,1,},好像不会背公式了。。但可以用单位根反演解一个通式

(1) f ( x ) = ∑ i = 0 ∞ [ d ∣ i ] x i i ! = 1 d ∑ i = 0 ∞ ∑ j = 0 d − 1 ( w d j x ) i i ! = 1 d ∑ j = 0 d − 1 e w d j x f(x)=\sum_{i=0}^\infty[d|i]\frac {x^i} {i!}=\frac 1 d\sum_{i=0}^\infty \sum_{j=0}^{d-1} \frac {(w_d^{j} x)^i} {i!}=\frac 1 d\sum_{j=0}^{d-1} e^{w_d^jx}\tag 1 f(x)=i=0[di]i!xi=d1i=0j=0d1i!(wdjx)i=d1j=0d1ewdjx(1)

而恰好在 p = 19491001 p=19491001 p=19491001 意义下,可以定义 w 3 = G p − 1 3 w_3=G^{\frac {p-1} {3}} w3=G3p1。把 d = 3 d=3 d=3 代入 ( 1 ) (1) (1) 式,可以得到:

f k ( x ) = 1 3 k ( e x + e w 3 1 x + e w 3 2 x ) k f^k(x)=\frac 1 {3^k}(e^x+e^{w_3^1x}+e^{w_3^2x})^k fk(x)=3k1(ex+ew31x+ew32x)k

f k ( x ) = 1 3 k ∑ i = 0 k ( k i ) e i x ( e w 3 1 x + e w 3 2 ) k − i f^k(x)=\frac 1 {3^k} \sum_{i=0}^k\binom k i e^{ix}(e^{w_3^1x}+e^{w_3^{2}})^{k-i} fk(x)=3k1i=0k(ik)eix(ew31x+ew32)ki

f k ( x ) = 1 3 k ∑ i = 0 k ( k i ) e i x ( ∑ j = 0 k − i ( k − i j ) e w 3 1 j + w 3 2 ( k − i − j ) ) f^k(x)=\frac 1 {3^k} \sum_{i=0}^k\binom k i e^{ix}\biggl( \sum_{j=0}^{k-i} \binom {k-i} j e^{w_3^1j+w_3^2(k-i-j)} \biggr) fk(x)=3k1i=0k(ik)eix(j=0ki(jki)ew31j+w32(kij))

然而先求右边括号里的再求左边是有问题的= =只好把所有的幂都合并

f k ( x ) = 1 3 k ∑ i = 0 k ( k i ) ( ∑ j = 0 k − i ( k − i j ) e i x + w 3 1 j x + w 3 2 ( k − i − j ) x ) f^k(x)=\frac 1 {3^k} \sum_{i=0}^k\binom k i \biggl( \sum_{j=0}^{k-i} \binom {k-i} j e^{ix+w_3^1jx+w_3^2(k-i-j)x} \biggr) fk(x)=3k1i=0k(ik)(j=0ki(jki)eix+w31jx+w32(kij)x)

同样暴力做,时间复杂度 O ( k 2 log ⁡ n ) O(k^2\log n) O(k2logn)

Code

#include <cstdio>
using namespace std;
typedef long long ll;
const int maxn=500010,mod=19491001;
const int G=7,w1=18827933,w2=663067;
template <typename Tp> inline int getmin(Tp &x,Tp y){return y<x?x=y,1:0;}
template <typename Tp> inline int getmax(Tp &x,Tp y){return y>x?x=y,1:0;}
template <typename Tp> inline void read(Tp &x)
{
    x=0;int f=0;char ch=getchar();
    while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
    if(ch=='-') f=1,ch=getchar();
    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    if(f) x=-x;
}
int n,k,d,ans,fac[maxn],inv[maxn];
int pls(int x,int y){return x+y>=mod?x+y-mod:x+y;}
int dec(int x,int y){return x<y?x-y+mod:x-y;}
int c(int n,int m){return (ll)fac[n]*inv[m]%mod*inv[n-m]%mod;}
int power(int x,int y)
{
	int res=1;
	for(;y;y>>=1,x=(ll)x*x%mod)
	  if(y&1)
	    res=(ll)res*x%mod;
	return res;
}
int main()
{
	read(n);read(k);read(d);
	fac[0]=1;
	for(int i=1;i<=k;i++) fac[i]=(ll)fac[i-1]*i%mod;
	inv[k]=power(fac[k],mod-2);
	for(int i=k-1;~i;i--) inv[i]=(ll)inv[i+1]*(i+1)%mod;
	if(d==1) printf("%d\n",power(k,n));
	else if(d==2)
	{
		for(int i=0;i<=k;i++) ans=(ans+(ll)c(k,i)*power(dec(pls(i,i),k),n))%mod;
		ans=(ll)ans*power(9745501,k)%mod;
		printf("%d\n",ans);
	}
	else
	{
		for(int i=0;i<=k;i++)
		{
			int tmp,sum=0;
			for(int j=0;j<=k-i;j++)
			{
				tmp=(i+(ll)w1*j+(ll)w2*(k-i-j))%mod;
				sum=(sum+(ll)c(k-i,j)*power(tmp,n))%mod;
			}
			ans=(ans+(ll)c(k,i)*sum)%mod;
		}
		ans=(ll)ans*power(12994001,k)%mod;
		printf("%d\n",ans);
	}
	return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值