Educational Codeforces Round 116 (Rated for Div. 2) E.Arena解题报告

发布于 2021-11-15  812 次阅读


先放题目链接:https://codeforces.com/problemset/problem/1606/E

本来以为这题自己写不出来的,结果没想到捅咕半天做出来了哈哈哈

emmm由于本人不是很会用markdown,所以这个的话就简单说说看法吧。

很明显的组合数学题,用dp[i][j]来表示还有i个人存活的,血量最大值为j的情况下符合最后题目要求的有多少种情况

状态转移方程为:dp[i][j]+=dp[k][j-(i-1)] (k is every number in 0~i)。然后,记忆化搜索吧

上代码吧

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const ll MOD=998244353;
ll C[505][505],dp[505][505];
ll n,x;
ll qpow(ll x, ll n){
    ll res = 1;
    while(n){
        if(n & 1) res =res * x % MOD;
        x = x * x % MOD;
        n/=2;
    }
    return res;
}
ll dfs(ll tot,ll maxn){
	if(tot==0||maxn==0) return 1;
	if(tot==1&&maxn>0) return 0;
	if(dp[tot][maxn]!=-1) return dp[tot][maxn];
	//cout<<tot<<" "<<maxn<<endl;
	dp[tot][maxn]=0;
	if(maxn<=(tot-1)){
		//cout<<"fff"<<endl;
		return dp[tot][maxn]=qpow(maxn,tot);
	}
	//cout<<"fff"<<endl;
	for(int i=0;i<=n;i++){
		dp[tot][maxn]+=dfs(i,max(0ll,maxn-tot+1))*C[tot][i]%MOD*qpow((tot-1),tot-i)%MOD;
		dp[tot][maxn]%=MOD;
	}
	return dp[tot][maxn];
}
int main(){
	//cout<<qpow(1,3);
	memset(dp,-1,sizeof(dp));
	for(int i=0;i<=500;i++) C[i][0]=1;
	for(int i=1;i<=500;i++){
		for(int j=1;j<=i;j++){
			C[i][j]=C[i-1][j-1]+C[i-1][j];C[i][j]%=MOD;
		}
	}
	
	cin>>n>>x;
	cout<<dfs(n,x);	
	return 0;
}

回忆这理想不够理想,沿途逛世间一趟只有向上