码迷,mamicode.com
首页 > 其他好文 > 详细

Tsinsen A1516. fx 数位dp

时间:2016-04-13 02:07:34      阅读:172      评论:0      收藏:0      [点我收藏+]

标签:

A1516. fx
时间限制:2.0s   内存限制:256.0MB   
总提交次数:164   AC次数:72   平均分:51.28
 
将本题分享到:
      
   
试题来源
  中国国家队清华集训 2013-2014 第四天
问题描述
  对于一个n位的十进制数x(AnAn-1……A1),我们定义它的权重为:
  F(x)=An*2n-1+An-1*2n-2+……+A1*20
  现在,给你两个十进制数A和B,请计算出在闭区间[0, B]之中,有多少个数x的权重不大于A的权重,即F(x)<=F(A)。由于答案可能很大,你只需要输出答案对1000000007(109 + 7)取模的结果即可。
输入格式
  第一行一个正整数T,表示测例的个数。
  随后T行,每行描述一个测例,包含两个非负整数A、B,之间用空格隔开。含义见问题描述。
输出格式
  对于每个测例,单独输出一行”Case #t: ans”,其中t表示测例编号,从1开始递增,ans表示该组测例的答案(对1000000007取模后的结果)。
样例输入
3
0 100
1 10
5 100
样例输出
Case #1: 1
Case #2: 2
Case #3: 13
样例说明
  对于Case #3,符合条件的数有0, 1, 2, 3, 4, 5, 10, 11, 12, 13, 20, 21, 100,共13个。

  //样例描述有修改,请注意!
数据规模及约定
  对于20%的数据,A, B <= 109
  对于30%的数据,A, B <= 1018

  对于100%的数据,A,B <= 10200,T<=5。
 
题解:
数位dp
f[i][j]为到第i位,差值之和为j的方案数.
但16和17行没有理解太懂,关于 差值+30 不太清楚。QAQ
如果哪位高人看懂了,可以留言。万分感谢。??Orz
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define MOD 1000000007
 4 int f[210][66],A[210],B[210];
 5 char s1[210],s2[210];
 6 int read()
 7 {
 8     int s=0,fh=1;char ch=getchar();
 9     while(ch<0||ch>9){if(ch==-)fh=-1;ch=getchar();}
10     while(ch>=0&&ch<=9){s=s*10+(ch-0);ch=getchar();}
11     return s*fh;
12 }
13 int Dfs(int len,int tot,int flag)//当前到达第len位,差值之和为tot,flag为是否限制(0代表不限制,1代表限制)
14 {
15     if(len==0)return tot>=0;
16     if(tot<-30)return 0;//这两句!!!
17     if(tot>30)tot=30;//这两句!!!
18     if(flag==0&&f[len][tot+30]!=-1)return f[len][tot+30];
19     int end=flag?B[len]:9,i,ret=0;
20     for(i=0;i<=end;i++)ret=(ret+Dfs(len-1,(tot+A[len]-i)*2,flag&&(i==end)))%MOD;
21     if(flag==0)f[len][tot+30]=ret;
22     return ret;
23 }
24 int main()
25 {
26     int case1=0,T,la,lb,i;
27     T=read();
28     while(T--)
29     {
30         scanf("\n%s %s",s1+1,s2+1);
31         la=strlen(s1+1);
32         lb=strlen(s2+1);
33         memset(A,0,sizeof(A));
34         memset(B,0,sizeof(B));
35         memset(f,-1,sizeof(f));
36         for(i=1;i<=la;i++)A[i]=s1[la-i+1]-0;//要从高位枚举,所以要把序列倒过来.
37         for(i=1;i<=lb;i++)B[i]=s2[lb-i+1]-0;//同上.
38         if(la>lb)swap(la,lb);//取出长度大的.
39         printf("Case #%d: %d\n",++case1,Dfs(lb,0,1));
40     }
41     fclose(stdin);
42     fclose(stdout);
43     return 0;
44 }

 

Tsinsen A1516. fx 数位dp

标签:

原文地址:http://www.cnblogs.com/Var123/p/5385146.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!