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; }