For a decimal number x with n digits (A
nA
n-1A
n-2 ... A
2A
1), we define its weight as F(x) = A
n * 2
n-1 + A
n-1 * 2
n-2 + ... + A
2 * 2 + A
1 * 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).
For each test case, there are two numbers A and B (0 <= A,B < 10 9)
3 0 100 1 10 5 100
Case #1: 1 Case #2: 2 Case #3: 13
题意:输入N,然后分别有N组数据,每次输入两个数a,b;a表示F[a],题意让求x在[0,b]区间内有多少满足F[x]<=F[a];F(x) = A n * 2 n-1 + A n-1 * 2 n-2 + ... + A 2 * 2 + A 1 * 1;
的意思是x的第n位的数字乘以2的(n-1)次方的和,如x=5,则F[x]=5*2^0=5; 再如:x=15,则F[x]=1*2^1+5*2^0=7;对于第三组样例:满足F[a]>=F[x]的条件的x有:0,1,2,3,4,5,10,11,12,13,20,21,100,共13个;
思路就是数位dp的思想,暴力枚举,求得满足的数,dp[i][j],i代表位,j代表F[x];
思路与前两个题一样 很清晰,直接套模板也行:
代码如下:#include<cstdio> #include<cstring> int dp[10][10005];//F[x]最大不会超过一万 int a[10]; int A,b; int sum; int dfs(int pos,int s,bool limit) { if(pos == -1) return s <= sum; if(s > sum) return 0; if(!limit && dp[pos][sum-s] != -1) return dp[pos][sum-s]; int up = limit ? a[pos] : 9; int tmp = 0; for(int i = 0; i <= up; i++) { tmp += dfs(pos - 1 , s + i * (1 << pos),limit && i == a[pos]); } if(!limit) dp[pos][sum-s] = tmp; return tmp; } int F(int x) { int p = 1,s = 0; while(x) { s += p * (x % 10); x /= 10; p *= 2; } return s; } int solve(int x) { int t = 0; while(x) { a[t++] = x%10; x /= 10; } return dfs(t-1,0,true); } int main() { int N,M = 1; scanf("%d",&N); memset(dp,-1,sizeof(dp)); while(N--) { scanf("%d %d",&A,&b); sum = F(A); printf("Case #%d: %d\n",M++,solve(b)); } return 0; }