2020camp-day6-J
dp[i],为在前n个数中,循环节为k(题目给的)的方案数
#include<cstdio>
#include<cstring>
#include<algorithm>
#define RE register
#define FOR(i,a,b) for(RE int i=a;i<=b;++i)
#define ROF(i,a,b) for(RE int i=a;i>=b;--i)
#define ll long long
#define sc(n) scanf("%d",&n)
using namespace std;
const int maxn = 1005;
const int mod = 998244353;
int n, T;
ll c[55], cn[55][55], dp[55], k;
void init()
{
FOR(i, 0, 50)
{
cn[i][0] = 1;
FOR(j, 1, i)cn[i][j] = (cn[i - 1][j - 1] + cn[i - 1][j]) % mod;
}
c[0] = c[1] = 1;
FOR(i, 2, 50)c[i] = c[i - 1] * i % mod;
}
int main()
{
init();
sc(T);
while(T--)
{
sc(n), scanf("%lld",&k);
memset(dp, 0, sizeof(dp));
dp[1] = dp[0] = 1;
FOR(i,2,n)
FOR(j,1,i)
if (k % j == 0)
//为什么不是A(i,j)?而是A(i-1,j-1)
//把i中一个数提出来,让剩下的(i-1)个数挑一个k扔进去,在把(i-2)数中挑一个扔进k的位置。。。直到最后把最先挑出的数放进去
dp[i] = (dp[i] + (cn[i - 1][j - 1]) * c[j - 1] % mod * dp[i - j] % mod) % mod;
printf("%lld\n", dp[n]);
}
return 0;
}

浙公网安备 33010602011771号