Bomb
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/65536 K (Java/Others)Total Submission(s): 16418 Accepted Submission(s): 6006
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?
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.
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
题意很简单,求1~n中含“49”的数字
学的第一道数位dp题= =总结在注释里,给出代码
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<stack>
#include<queue>
#include<algorithm>
#include<string>
#include<cstring>
#include<cmath>
#include<vector>
#include<map>
#include<set>
#define eps 1e-8
#define zero(x) (((x>0?(x):-(x))-eps)
#define mem(a,b) memset(a,b,sizeof(a))
#define memmax(a) memset(a,0x3f,sizeof(a))
#define pfn printf("\n")
#define ll __int64
#define ull unsigned long long
#define sf(a) scanf("%d",&a)
#define sf64(a) scanf("%I64d",&a)
#define sf264(a,b) scanf("%I64d%I64d",&a,&b)
#define sf364(a,b,c) scanf("%I64d%I64d%I64d",&a,&b,&c)
#define sf2(a,b) scanf("%d%d",&a,&b)
#define sf3(a,b,c) scanf("%d%d%d",&a,&b,&c)
#define sf4(a,b,c,d) scanf("%d%d%d%d",&a,&b,&c,&d)
#define sff(a) scanf("%f",&a)
#define sfs(a) scanf("%s",a)
#define sfs2(a,b) scanf("%s%s",a,b)
#define sfs3(a,b,c) scanf("%s%s%s",a,b,c)
#define sfd(a) scanf("%lf",&a)
#define sfd2(a,b) scanf("%lf%lf",&a,&b)
#define sfd3(a,b,c) scanf("%lf%lf%lf",&a,&b,&c)
#define sfd4(a,b,c,d) scanf("%lf%lf%lf%lf",&a,&b,&c,&d)
#define sfc(a) scanf("%c",&a)
#define ull unsigned long long
#define pp pair<int,int>
#define debug printf("***\n")
const double PI = acos(-1.0);
const double e = exp(1.0);
const int INF = 0x7fffffff;;
template<class T> T gcd(T a, T b) { return b ? gcd(b, a % b) : a; }
template<class T> T lcm(T a, T b) { return a / gcd(a, b) * b; }
template<class T> inline T Min(T a, T b) { return a < b ? a : b; }
template<class T> inline T Max(T a, T b) { return a > b ? a : b; }
bool cmpbig(int a, int b){ return a>b; }
bool cmpsmall(int a, int b){ return a<b; }
using namespace std;
ll numdp[20][3];//因为数据范围的n位数不会超过10,所以开到大于10就行,而且只用考虑三种状况
//0表示前i位中没有49的情况
//1表示前i位中没有49,但第i位是9的情况
//2表示前i位中有49的情况
void init() //预处理出所有位数的情况
{
int i;
mem(numdp,0);
numdp[0][0]=1;//初始化
for(i=1;i<20;i++)
{
numdp[i][0]=(ll)numdp[i-1][0]*10-numdp[i-1][1]; //这里求的是到第i位不存在49的情况,可能有点不好想,我们可以这么想
//前i位中没有49的情况肯定是包含前i位中没有49,但第i位是9的情况的,我们将第i位是4的排除掉即可。
numdp[i][1]=(ll)numdp[i-1][0]; //前面不存在49的情况,这时将9安排在第i位
numdp[i][2]=(ll)numdp[i-1][2]*10+numdp[i-1][1]; //继承前面i位中有49的情况和前i-1位中没有49,但第i-1位是9,第i位是4的情况
}
}
int main()
{
// freopen("data.in","r",stdin);
int t;
init();
sf(t);
while(t--)
{
ll n;
sf64(n);
n++; //因为题目要求1~n 所以n++一下
int bit[20];
mem(bit,0);
int len=0;
bool flag=false;
while(n)
{
bit[++len]=n%10; //反向取位数
n/=10;
}
bit[len+1]=0; //最高位+1设为0
ll sum=0;
for(int i=len;i>=1;i--)
{
sum+=(ll)bit[i]*numdp[i-1][2]; //直接乘前面有49的个数
if(flag)
sum+=(ll)bit[i]*numdp[i-1][0]; //因为我们在求numdp[i-1][0]并没有将numdp[i-1][2]包含进去,所以这里要加上
if((!flag)&&bit[i]>4)
sum+=numdp[i-1][1];
if(bit[i]==9&&bit[i+1]==4)
flag=true;
}
printf("%I64d\n",sum);
}
return 0;
}