2229:Sumsets
概要
整数n(<10^6)が与えられる。nを2のべき数の和で表す方法の総数を求める問題。
よくある、硬貨の組合せの問題。dp[支払う金額][使う最大の硬貨]とすると計算量O(支払う金額*硬貨の枚数)で求めることができて、この場合の硬貨の枚数は2^20>10^6だから2^0...2^19の20枚で十分。なので計算量2*10^7。ちょっと厳しいものがあるけど何とかなる範囲。1回TLEもらったけど細かいところを修正して無事AC。
int main(){ int twos[20]; int n, i, j; const int mod=1000000000; static int dp[1000003][20]; scanf("%d",&n); REP(i,20) twos[i] = (1<<i); REPONE(i,n)REP(j,20) dp[i][j] = 0; REP(j,20)dp[0][j] = dp[1][j] = 1; for(i=2;i<=n;i++){ REP(j,20){ if((i-twos[j])>=0){ dp[i][j] = dp[i-twos[j]][j]; } else break; } REPONE(j,19) dp[i][j] = (dp[i][j] + dp[i][j-1])%mod; } printf("%d\n",dp[n][19]); return 0; }