HDU 4945 2048
Question Link
Question: Given a sequence, how many sub-sequences can be merged into 2048
Train of Thought: Put 2, 4, 8 .. 2048 consider these numbers. Other numbers cannot be included in the composition. Based on these numbers, DP [I] [J] indicates the I number, and the number of cases for J, and then the number of each number enumeration, you can use the combination number to transfer the status. Here there is a pruning, that is, if the number is increased by more than 2048, the sum of the numbers in the subsequent sections is added to 2048. You can use the formula to solve the problem one step, so that the overall complexity can satisfy the problem. Then the time limit for this question is too tight. If the reverse element within 10 w times out, it will time out without preprocessing.
Code:
# Include <cstdio> # include <cstring> # include <algorithm> using namespace STD; typedef long ll; const int mod = 998244353; inline void scanf _ (Int & num) // no negative number {char in; while (in = getchar ()> '9' | in <'0'); num = In-'0 '; while (in = getchar (), in> = '0' & in <= '9') num * = 10, num + = In-'0 ';} int N, V [2049], MI [15], M, CNT [15]; int DP [15] [2049], mi2 [100005], invv [100005]; bool istwo [2049]; void Init () {int num; M = 0; Memset (CNT, 0, sizeof (CNT); For (INT I = 0; I <n; I ++) {scanf _ (Num); If (! Istwo [num]) {M ++; continue;} else CNT [V [num] ++ ;}} int inv (int n) {int ans = 1; int K = mod-2; while (k) {If (K & 1) ans = (LL) ans * n % MOD; n = (LL) N * n % MOD; k> = 1;} return ans;} int solve () {memset (DP, 0, sizeof (DP); DP [0] [0] = 1; for (INT I = 1; I <= 12; I ++) {for (Int J = 0; j <= 2048; j + = mi [I]) {If (DP [I-1] [J] = 0) continue; int c = 1, s = 0; int sum = J; For (int K = 0; k <= CNT [I]; k ++) {int x = sum; If (x = 2048) {DP [I] [x] = (LL) DP [I-1] [J] * (mi2 [CNT [I]-S) % mod + dp [I] [x]; if (DP [I] [x] <0) DP [I] [x] + = MOD; If (DP [I] [x]> = mod) DP [I] [x]-= MOD; break;} If (X % MI [I + 1]) x = x-mi [I]; DP [I] [x] = (LL) DP [I-1] [J] * C % mod + dp [I] [x]; if (DP [I] [x]> = mod) DP [I] [x]-= MOD; S + = C; If (S> = mod) s-= MOD; C = (LL) C * (CNT [I]-k) % mod * invv [k + 1] % MOD; sum + = mi [I];}} Return (LL) DP [12] [2048] * mi2 [m] % MOD;} int main () {memset (istwo, false, sizeof (istwo )); memset (v,-1, sizeof (v); MI [0] = 0; V [0] = 0; For (INT I = 1, j = 1; I <= 2048; I * = 2, J ++) {istwo [I] = true; V [I] = J; MI [J] = I ;} mi [13] = 4096; For (INT I = 1; I <= 2048; I ++) {If (V [I] =-1) V [I] = V [I-1];} mi2 [0] = 1; for (INT I = 1; I <= 100000; I ++) {invv [I] = inv (I); mi2 [I] = mi2 [I-1] * 2% MOD;} int CAS = 0; while (~ Scanf ("% d", & N) {Init (); printf ("case # % d: % d \ n", ++ cas, solve ();} return 0 ;}