1. 程式人生 > 其它 >【BZOJ3157 國王奇遇記】+【BZOJ3516 國王奇遇記加強版 】題解

【BZOJ3157 國王奇遇記】+【BZOJ3516 國王奇遇記加強版 】題解

題目連結

由於BZOJ已掛,這裡是黑暗爆炸和hydro的備份

黑暗爆炸:

hydro:

題目

Katharon 國有著悠久的歷史,每個慕名而來的遊客都渴望能在 Katharon 國發現一些奇怪的寶藏。而作為國王的 Kanari 君也夢想著有一天發現自己國家的寶藏,從而成為世界上最富有的人。 Kanari 國王和 katherine 皇后憑著 14 年真摯的感情,數十年如一日甜蜜地生活在一起。前幾天恰逢勞動節放假, Kanari 國王便和 Katherine 皇后一同前往電影院觀看了最新出版的電影《致青春》。看完之後兩人對青春又有了更深刻的認識。然而在返程的路上,他們突然在路邊的小樹林裡發現了一塊奇怪的石板,上面印著一行小字:“如果你能破解下面表示式的結果,你就可以擁有 Katharon 國最珍貴的財產。”這時 Kanari 國王和 Katherine 皇后再也顧不上秀恩愛了,只好拿出草紙拼命計算這個表示式的結果。可是兩人能力有限,現在,他們找到擅長數學的你,想請你來幫助他們完成這個願望,如果你能回答正確,他們願意把 Katharon 國最珍貴的財產分給你一半哦。這個表示式就是:

∑i=1nim×mi\sum_{i=1}^n i^m \times m^i
i=1∑n​im×mi

思路

題目就是求:

\[\Large\sum_{i=1}^ni^mm^i \]

由於 \(m\) 很小,\(n\) 很大,所以考慮dp。

\(dp_i\) 表示:

\[\Large dp_i=\sum_{j=1}^nj^im^j \]

假設我們要求 \((m-1)dp_i\)

則:

\[\Large (m-1)dp_i=m\times dp_i-dp_i \]

帶入 \(dp\) 的定義:

\[\Large m\times \sum_{j=1}^nj^im^j-\sum_{j=1}^nj^im^j \]

把前面的 \(m\)

弄進去:

\[\Large \sum_{j=1}^nj^im^{j+1}-\sum_{j=1}^nj^im^j \]

\(m^{j+1}\) 變成 \(m^j\)

\[\Large \sum_{j=2}^{n+1}(j-1)^im^j-\sum_{j=1}^nj^im^j \]

\(\sum_{j=2}^{n+1}\) 變成 \(\sum_{j=1}^n\),也就是我們要減去一項 \(j=1\) 再加上一項 \(j=n+1\)

\[\Large \sum_{j=1}^n(j-1)^im^j+(n+1-1)^mm^{n+1}-(1-1)^mm^1-\sum_{j=1}^nj^im^j \]

化簡:

\[\Large \sum_{j=1}^n(j-1)^im^j+n^mm^{n+1}-0^im^1-\sum_{j=1}^nj^mm^j \]\[\Large n^mm^{n+1}+\sum_{j=1}^n(j-1)^im^j-\sum_{j=1}^nj^im^j \]

後面的合併:

\[\Large n^mm^{n+1}+\sum_{j=1}^nm^j((j-1)^i-j^i) \]

其中 \((j-1)^m\) 可以用二項式定理化簡。

\[\Large n^mm^{n+1}+\sum_{j=1}^nm^j(\sum_{k=0}^iC_i^kj^k(-1)^{i-k}-j^i) \]

強行把 \(k=i\) 的情況提出來:

\[\Large n^mm^{n+1}+\sum_{j=1}^nm^j(\sum_{k=0}^{i-1}C_i^kj^k(-1)^{i-k}+C_i^ij^i(-1)^{i-i}-j^i) \]

化簡:

\[\Large n^mm^{n+1}+\sum_{j=1}^nm^j(\sum_{k=0}^{i-1}C_i^kj^k(-1)^{i-k}+j^i-j^i) \]\[\Large n^mm^{n+1}+\sum_{j=1}^nm^j(\sum_{k=0}^{i-1}C_i^kj^k(-1)^{i-k}) \]

調整一下順序:

\[\Large n^mm^{n+1}+\sum_{k=0}^{i-1}C_i^k(-1)^{i-k}\times\sum_{j=1}^nj^km^j \]

明顯,\(\sum_{j=1}^nm^jj^k\) 就是 \(dp\) 的定義,所以

\[\Large n^mm^{n+1}+\sum_{k=0}^{i-1}C_i^k(-1)^{i-k}\times dp_k \]

而這個式子是 \((m-1)dp_i\),所以 \(dp_i\) 為:

\[\Large dp_i=\frac{n^mm^{n+1}+\sum_{k=0}^{i-1}C_i^k(-1)^{i-k}\times dp_k}{m-1} \]

\(O(m^2)\) dp,初始化注意一下即可。

Code

// Problem: L - 國王奇遇記
// Contest: Virtual Judge - 2021.12.12校內作業
// URL: https://vjudge.net/contest/472915#problem/L
// Memory Limit: 1024 MB
// Time Limit: 1000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include<bits/stdc++.h>
using namespace std;
#define int long long
inline int read(){int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;
ch=getchar();}while(ch>='0'&&ch<='9'){x=(x<<1)+
(x<<3)+(ch^48);ch=getchar();}return x*f;}
#define mo 1000000007
#define N 1020
int n, m, i, j, k; 
int jc[N], f[N], p_1[N]; 

int kuai(int a, int b)
{
	int ans=1; 
	while(b)
	{
		if(b&1) ans=(ans*a)%mo; 
		b>>=1; 
		a=(a*a)%mo; 
	}
	return ans; 
}

int C(int m, int n)
{
	return jc[m]*kuai(jc[n]*jc[m-n]%mo, mo-2)%mo; 
}

signed main()
{
//	freopen("tiaoshi.in","r",stdin);
//	freopen("tiaoshi.out","w",stdout);
	for(i=jc[0]=1; i<=1010; ++i) 
		jc[i]=jc[i-1]*i%mo; 
	for(i=0; i<=1010; ++i) p_1[i]=(i%2==1 ? -1 : 1); 
	n=read(); m=read(); 
	if(m==1) return printf("%lld", (1+n)*n/2%mo), 0; 
	f[0]=(kuai(m, n+1)-m)*kuai(m-1, mo-2)%mo; 
	for(i=1; i<=m; ++i)
	{
		f[i]=kuai(n, i)*kuai(m, n+1)%mo; 
		for(k=0; k<=i-1; ++k)
			f[i]=(f[i]+C(i, k)*f[k]%mo*p_1[i-k])%mo; 
		f[i]=f[i]*kuai(m-1, mo-2)%mo; 
	}
	printf("%lld", (f[m]%mo+mo)%mo); 
	return 0;
}