4734 F(x) 數位dp
阿新 • • 發佈:2018-12-09
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).
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 < 10 9)
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
題解:dp[i][j] 表示第i位0的個數-1的個數的數量 因為可能為負數 ,所以 初始化為35 (輸入轉換2進位制最多32位)
要從第一個不是0的位置開始計算,所以 在模板的情況下加一個lead即可
#include<iostream> #include<cstdio> #include<cstring> using namespace std; typedef long long ll; #define PI acos(-1) const int N=1e5+10; #define eps 0.00001 int dp[35][65]; int wei[35]; int dfs(int pos,int st,int lead,int limit) { if(pos==0) { //cout<<st<<endl; return st>=35; } if(!limit&&!lead&&dp[pos][st]!=-1) return dp[pos][st]; int en=limit?wei[pos]:1; int ans=0; for(int i=0;i<=en;i++) { // cout<<st<<" "<<i<<" "<<pos<<endl; if(lead&&i==0) ans+=dfs(pos-1,st,lead,limit&&i==en); else ans+=dfs(pos-1,st+(i==0?1:-1),lead&&i==0,limit&&i==en); } if(!lead&&!limit) dp[pos][st]=ans; return ans; } int solve(int x) { int len=0; while(x) { wei[++len]=x&1; x>>=1; } return dfs(len,35,1,1); } int main() { memset(dp,-1,sizeof(dp)); int a,b; while(~scanf("%d%d",&a,&b)) { //cout<<solve(b)<<" "<<solve(a-1)<<endl; printf("%d\n",solve(b)-solve(a-1)); } return 0; }