bzoj 1025 [SCOI2009]遊戲 dp
阿新 • • 發佈:2018-08-14
mat node ans inline cpp 問題 max return emp
題面
題目傳送門
解法
顯然,可以回到初始狀態就意味著一定由若幹個環組成
假設環的長度為\(l_i\)
那麽,我們可以得到\(\sum l_i=n\)
不考慮自環的情況,那麽\(\sum l_i≤n\)
將\(n\)以內的質因數全部篩出,強制每一次只取某一個質數的次冪,那麽就可以解決重復計數的問題
時間復雜度:\(O(n^2)\)
代碼
#include <bits/stdc++.h> #define int long long #define N 1010 using namespace std; template <typename node> void chkmax(node &x, node y) {x = max(x, y);} template <typename node> void chkmin(node &x, node y) {x = min(x, y);} template <typename node> void read(node &x) { x = 0; int f = 1; char c = getchar(); while (!isdigit(c)) {if (c == ‘-‘) f = -1; c = getchar();} while (isdigit(c)) x = x * 10 + c - ‘0‘, c = getchar(); x *= f; } int len, a[N], f[N][N]; bool prime(int x) { for (int i = 2; i * i <= x; i++) if (x % i == 0) return false; return true; } void sieve(int n) { len = 0; for (int i = 2; i <= n; i++) if (prime(i)) a[++len] = i; } main() { int n; read(n); sieve(n); f[0][0] = 1; for (int i = 1; i <= len; i++) for (int j = 0; j <= n; j++) { f[i][j] += f[i - 1][j]; for (int k = a[i]; j + k <= n; k = k * a[i]) f[i][j + k] += f[i - 1][j]; } int ans = 0; for (int i = 0; i <= n; i++) ans += f[len][i]; cout << ans << "\n"; return 0; }
bzoj 1025 [SCOI2009]遊戲 dp