hdu5106 小于x的数(二进制1确定的数)的和 数位dp(first mine)
学过数位dp,第一次用那个模板用自己的思路敲出来的dfs代码2333
还尼玛用了结构体瞬间觉得高大上逼格升升升===
吃颗药冷静一下,结构体返回的是:
1.pos及其下面的符合已定sum的数目
2.pos及其下面的符合已定sum的数的和
然后开两个数组保存一下记忆化:
1 #include<stdio.h> 2 #include<string.h> 3 #define LL long long 4 #define MOD 1000000007 5 struct dian{ 6 int num,sum; 7 }; 8 int n,dp[1005][1005],num[1005],bit[1005],t[1005][1005]; 9 char s[1005]; 10 dian dfs(int pos,int sum,int x,int limit) 11 { 12 int tmp,i,ans=0,ans2=0; 13 dian n1; 14 if (sum+pos<n||(pos==0&&limit)) 15 { 16 n1.num=n1.sum=0; 17 return n1; 18 } 19 if (pos==0) 20 { 21 n1.num=sum==n?1:0; 22 n1.sum=sum==n?x:0; 23 return n1; 24 } 25 if (!limit&&dp[pos][sum]!=-1) 26 { 27 n1.num=t[pos][sum]; 28 n1.sum=(int)(((LL)x*(LL)n1.num+dp[pos][sum])%MOD); 29 return n1; 30 } 31 tmp=limit?num[pos]:1; 32 for (i=0;i<=tmp;i++) 33 { 34 n1=dfs(pos-1,sum+i,(x+i*(bit[pos-1]))%MOD,limit&&(i==tmp)); 35 ans=(ans+n1.sum)%MOD; 36 ans2=(ans2+n1.num)%MOD; 37 } 38 if (!limit) 39 { 40 t[pos][sum]=ans2; 41 dp[pos][sum]=(int)((((LL)ans-(LL)ans2*(LL)x)%MOD+MOD)%MOD); 42 } 43 n1.sum=ans; n1.num=ans2; 44 return n1; 45 } 46 int main() 47 { 48 int cnt,i; 49 bit[0]=1; 50 for (i=1;i<1000;i++) 51 bit[i]=(bit[i-1]*2)%MOD; 52 while (~scanf("%d%s",&n,s)) 53 { 54 cnt=strlen(s); 55 memset(dp,-1,sizeof(dp)); 56 memset(t,-1,sizeof(t)); 57 for (i=cnt;i>=1;i--) 58 num[i]=s[cnt-i]-'0'; 59 printf("%d\n",dfs(cnt,0,0,1).sum); 60 } 61 }