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?
Now the counter-terrorist knows the number N. They want to know the final points of the power. Can you help them?
The input terminates by end of file marker.
3 1 50 500
0 1 15
From 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.
题目大意:
求1到n直间含有49的个数
思路代码(超时):
通过跑了一遍暴力发现每1000个数里有20个符合题意(从1 开始),所以用了找规律的方法,结果T了。。。。。
如果数据比较水应该是可以用的
#include<stdio.h>
#include<string.h>
using namespace std;
typedef long long ll;
int Is(ll x){
int flag=0;
while(x){
if(x%10==9){
flag=1;
x/=10;
}
if(x%10==4&&flag) return 1;
if(x%10==9) flag=1;
else flag=0;
x/=10;
}
return 0;
}
int main(){
int T;
scanf("%d",&T);
while(T--){
ll n;
scanf("%d",&n);
ll cnt=0,i;
cnt=n/1000*20;
for(i=n/1000*1000;i<=n;i++)
cnt+=Is(i);
printf("%lld\n",cnt);
}
return 0;
}
数位DP思路:(正解)
#include<stdio.h>
#include<string.h>
using namespace std;
typedef long long ll;
int a[65];
ll dp[65][3];
//dp[pos][have];
//pos : 当前数位
//have: 0:前一位不是4 :1:前一位不是4 2:出现过49
ll Dfs(int pos,int have,bool limit){
if(pos==-1) return have==2;
if(!limit&&dp[pos][have]!=-1) return dp[pos][have];
int up=limit?a[pos]:9;
ll cnt=0,i;
int havex;
for(i=0;i<=up;i++){
havex=have;
if(have==0&&i==4) havex=1;
if(have==1&&i!=4) havex=0;
if(have==1&&i==9) havex=2;
cnt+=Dfs(pos-1,havex,limit&&i==a[pos]);
}
if(!limit) dp[pos][have]=cnt;
return cnt;
}
ll solve(ll x){
int pos=0;
while(x){
a[pos++]=x%10;
x/=10;
}
return Dfs(pos-1,0,true);
}
int main(){
int T;
scanf("%d",&T);
memset(dp,-1,sizeof(dp));
while(T--){
ll n;
scanf("%lld",&n);
printf("%lld\n",solve(n));
}
return 0;
}