您的位置:首页 > 其它

HDU 3555 数位DP入门(两种思路)

2017-01-24 21:37 267 查看


Bomb

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/65536 K (Java/Others)

Total Submission(s): 16813    Accepted Submission(s): 6161


Problem Description

The counter-terrorists found a time bomb in the dust. But this time the terrorists improve on the time bomb. The number sequence of the time bomb counts from 1 to N. If the current number sequence includes the sub-sequence "49", the power of the blast would
add one point.

Now the counter-terrorist knows the number N. They want to know the final points of the power. Can you help them?

 

Input

The first line of input consists of an integer T (1 <= T <= 10000), indicating the number of test cases. For each test case, there will be an integer N (1 <= N <= 2^63-1) as the description.

The input terminates by end of file marker.

 

Output

For each test case, output an integer indicating the final points of the power.

 

Sample Input

3
1
50
500

 

Sample Output

0
1
15

HintFrom 1 to 500, the numbers that include the sub-sequence "49" are "49","149","249","349","449","490","491","492","493","494","495","496","497","498","499",
so the answer is 15.

 

简单的数位DP入门题,具体分析方法可参加我的上一篇博文。 博客链接

下面是两种思路的代码:

#include <bits/stdc++.h>
using namespace std;

__int64 dp[15][3];

//dp[i][0] 合法数
//dp[i][1] 9开头的合法数
//dp[i][2] 含49的非法数

void init(void){
memset(dp,0,sizeof(dp));
dp[0][0] = 1;
int i;
for(i=1 ;i<15 ;i++){
dp[i][0] = dp[i-1][0] * 10 - dp[i-1][1];
dp[i][1] = dp[i-1][0];
dp[i][2] = dp[i-1][2] * 10 + dp[i-1][1];
}
}

__int64 solve(__int64 x){
int len = 0,digit[21];
while(x){
digit[++len] = x % 10;
x /= 10;
}
digit[len+1] = 0;
int i;
__int64 ans = 0;
bool flag = false;
for(i=len ;i>0 ;i--){
ans += digit[i] * dp[i-1][2];
if(flag)
ans += dp[i-1][0] * digit[i];
if(!flag && digit[i] > 4)
ans += dp[i-1][1];
if(digit[i+1] == 4 && digit[i] == 9)
flag = true;
}
return ans;
}

int main(){
init();
int T;
scanf("%d",&T);
while(T--){
__int64 n;
scanf("%I64d",&n);
printf("%I64d\n",solve(n+1));
}
return 0;
}

二:

#include <bits/stdc++.h>
using namespace std;

__int64 dp[21][10];

void init(void){
memset(dp,0,sizeof(dp));
dp[0][0] = 1;
int i,j,k;
for(i=1 ;i<21 ;i++){
for(j=0 ;j<10 ;j++){
for(k=0 ;k<10 ;k++){
if(!(j==4 && k==9))
dp[i][j] += dp[i-1][k];
}
}
}
}

__int64 solve(__int64 x){
__int64 tem = x;
int len = 0,digit[21];
while(x){
digit[++len] = x % 10;
x /= 10;
}
digit[len+1] = 0;
int i,j;
__int64 ans = 0;
for(i=len ;i>0 ;i--){
for(j=0 ;j<digit[i] ;j++){
if(!(digit[i+1] == 4 && j == 9)){
ans += dp[i][j];
}
}
if(digit[i+1] == 4 && digit[i] == 9)
break;
}
return tem - ans;
}

int main(){
init();
int T;
scanf("%d",&T);
while(T--){
__int64 n;
scanf("%I64d",&n);
printf("%I64d\n",solve(n+1));
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: