F(x)
Time Limit: 1000/500 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Problem Description
For a decimal number x with n digits (AnAn-1An-2 ... A2A1), we define its weight as F(x) = An * 2n-1 + An-1 * 2n-2 + ... + A2 * 2 + A1 * 1. Now you are given two numbers A and B, please calculate how many numbers are there between 0 and B, inclusive, whose weight is no more than F(A).
(我还是翻译一下吧,不然哪天我自己都读不懂了(>_<))
(对于一个有n位(这n位从高位到低位分别是AnAn-1An-2 ... A2A1)的十进制数,我们定义它的权值F(x)=An * 2n-1 + An-1 * 2n-2 + ... + A2 * 2 + A1 * 1.现在给你两个数A,B,请计算[0,B]范围内有多少个权值<=F(A)的数)
Input
The first line has a number T (T <= 10000) , indicating the number of test cases.
For each test case, there are two numbers A and B (0 <= A,B < 109)
For each test case, there are two numbers A and B (0 <= A,B < 109)
Output
For every case,you should output "Case #t: " at first,
without quotes. The t is the case number starting from 1. Then output the
answer.
Sample Input
3
0 100
1 10
5 100
Sample Output
Case #1: 1
Case #2: 2
Case #3: 13
Recommend
Solution
数位dp.
dp[i][j]表示枚举到第i位,剩下的数位的权值和的限制为<=j
很正常的一道数位dp.
但是我很智障,Case的第一个大写打成了小写,莫名其妙地wa了,差点就开始对拍了.还是懒一点比较好,直接复制过来.
#include<algorithm> #include<iostream> #include<cstring> #include<cstdlib> #include<cstdio> #include<cmath> using namespace std; int mi[13],dp[13][4611],oo[13]; inline int read() { register int ans=0,f=1;char ch=getchar(); while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();} while(isdigit(ch)) {ans=ans*10+ch-'0';ch=getchar();} return ans*f; } inline int reada() { register int ans=0,f=1;char ch=getchar(); while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();} while(isdigit(ch)) {ans=ans*2+ch-'0';ch=getchar();} return ans*f; } int dfs(int wi,int cha,int lim) { if(wi<1) return 1; if(!lim&&dp[wi][cha]>-1) return dp[wi][cha]; int o=lim? oo[wi]:9; int ans=0; for(int i=0;i<=o;i++) { if(i*mi[wi-1]>cha) break; ans+=dfs(wi-1,cha-i*mi[wi-1],lim&&i==oo[wi]); } if(!lim) dp[wi][cha]=ans; return ans; } int sol(int a,int b) { int w=0; while(b) { oo[++w]=b%10; b/=10; } return dfs(w,a,1); } int main() { int cas,a,b; ///case重名 cas=read(); mi[0]=1; for(int i=1;i<=10;i++) mi[i]=2*mi[i-1]; memset(dp,-1,sizeof(dp)); for(int i=1;i<=cas;i++) { a=reada();b=read(); printf("Case #%d: ",i); printf("%d ",sol(a,b)); } return 0; }