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 }
View Code

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5106

posted on 2014-12-16 21:35  xiao_xin  阅读(220)  评论(0编辑  收藏  举报

导航