题目描述
输入
从文件segment.in中读入数据.
一行三个整数n, m, k.
输出
输出到文件segment.out中.
一个整数表示答案对998244353取模的结果.
n*m<=100000
又是一个关于线段的题,但是这个题的线段并不是特别重要,以至于我们可以直接将他拆成两个端点来考虑(一般只考虑端点比较简单)
然后就是愉快的DP了(出题人挖了好多坑,一般人看到(li>li-1 , ri>ri-1)就会绕死在线段DP上)
ACcode:
#include<cstdio>
#include<cstring>
#include<cctype>
#include<algorithm>
#define maxn 100005
#define mod 998244353
using namespace std;
int n,m,k;
int dp[2][400][400],f[2][400][400],fac[400];
inline int pow(int base,int k)
{
int ret=1;
for(;k;k>>=1,base=1ll*base*base%mod) if(k&1) ret=1ll*base*ret%mod;
return ret;
}
inline void add(int &a,int b)
{
a+=b;
if(a>mod) a-=mod;
}
int main()
{
//freopen("segment.in","r",stdin);
//freopen("segment.out","w",stdout);
scanf("%d%d%d",&n,&m,&k);
if(n>=m)
{
printf("0\n");
return 0;
}
for(int i=1;i<=n;i++) fac[i]=pow(i,k);
int now=1,pre=0;
dp[pre][0][0]=1;
for(int i=1;i<=m;i++)
{
for(int a=0;a<=n;a++)
for(int b=0;b<=n;b++)
dp[now][a][b]=f[now][a][b]=0;
for(int a=0;a<=n;a++)
for(int b=0;b<=a;b++)
if(dp[pre][a][b])
{
add(dp[now][a][b],dp[pre][a][b]);
add(dp[now][a+1][b],dp[pre][a][b]);
add(dp[now][a][b+1],dp[pre][a][b]);
add(dp[now][a+1][b+1],dp[pre][a][b]);
}
for(int a=0;a<=n;a++)
for(int b=0;b<=a;b++)
f[now][a][b]=1ll*dp[now][a][b]*fac[a-b]%mod;
for(int a=0;a<=n;a++)
for(int b=0;b<=a;b++)
{
add(f[now][a][b],f[pre][a][b]);
add(f[now][a+1][b],f[pre][a][b]);
add(f[now][a][b+1],f[pre][a][b]);
add(f[now][a+1][b+1],f[pre][a][b]);
}
swap(pre,now);
}
printf("%d\n",f[pre][n][n]);
}