Arena dp 逆序思维

There are nn heroes fighting in the arena. Initially, the ii-th hero has a_iai​ health points.

The fight in the arena takes place in several rounds. At the beginning of each round, each alive hero deals 11 damage to all other heroes. Hits of all heroes occur simultaneously. Heroes whose health is less than 11 at the end of the round are considered killed.

If exactly 11 hero remains alive after a certain round, then he is declared the winner. Otherwise, there is no winner.

Your task is to calculate the number of ways to choose the initial health points for each hero a_iai​, where 1 \le a_i \le x1≤ai​≤x, so that there is no winner of the fight. The number of ways can be very large, so print it modulo 998244353998244353. Two ways are considered different if at least one hero has a different amount of health. For example, [1, 2, 1][1,2,1] and [2, 1, 1][2,1,1] are different.

Input

The only line contains two integers nn and xx (2 \le n \le 500; 1 \le x \le 5002≤n≤500;1≤x≤500).

Output

Print one integer — the number of ways to choose the initial health points for each hero a_iai​, where 1 \le a_i \le x1≤ai​≤x, so that there is no winner of the fight, taken modulo 998244353998244353.

Sample 1

InputcopyOutputcopy
2 5
5

Sample 2

InputcopyOutputcopy
3 3
15

Sample 3

InputcopyOutputcopy
5 4
1024

Sample 4

InputcopyOutputcopy
13 37
976890680

​
​
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 510;
const int mod = 998244353;
typedef long long ll;
int C[MAXN][MAXN],dp[MAXN][MAXN];
void intc()
{
	for(int i = 1;i < MAXN; i++){
		C[i][0] = C[i][i] = 1;
		for(int j = 1;j < i; j++){
			C[i][j] = (C[i-1][j] + C[i-1][j-1])%mod;
		}
	}
}
ll ksm(ll a,ll b) {
    ll res = 1, base = a;
    while(b) {
		if(b & 1) {
		    res = (res * base) % mod;
		}
		base = (base * base) % mod;
		b >>= 1;
    }
    return res;
}
inline ll sub ( ll a, ll b ) { return ((a - b) % mod + mod) % mod; }
int main()
{
	int n,x;
	cin >> n >> x;
	intc();//dp[i][j]表示有i个英雄 生命值最大为j时最终有英雄存活的方案数
	for(int i = 1;i <= x; i++) dp[1][i] = i;
	for(int i = 2;i <= n; i++){
		for(int j = i; j <= x; j++){
			for(int l = 0;l < i; l++){//枚举下一轮死亡的英雄个数 
				dp[i][j] = (dp[i][j]+dp[i-l][j-i+1]*ksm(i-1,l)%mod*C[i][l]%mod)%mod;
			}//下一轮的英雄个数为i-l个 最大的生命值为j-i+1 
		}  //死亡的英雄的生命值的可能数为i-1 的l次方 每个英雄的生命值的范围在1—i-1
	}   //从i个英雄里挑选l个死亡的英雄 方案数为C[i][j]
	cout << sub(ksm(x,n),dp[n][x]);//总方案减去有英雄存活的方案
	return 0;
}

​

​

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值