啊哈是从CSDN搬过来的啦——(日历上没有下划线不爽)
传呀传呀传送门
好久没有写题解了的说QAQ
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?
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.
For each test case, output an integer indicating the final points of the power.
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.
求小于等于n的数中包含49的数有多少
首先肯定是想到DP:
设f[i]表示长度为i的数中有多少包含"49"
比方说n=56789时
假设我们要找的数可以表示为\(\bar{a_5a_4a_3a_2a_1}\)也就是说等于\(a_5*10000+a_4*1000+a_3*100+a_2*10+a_1\),我们考虑来枚举这个数——
因为它一定比n小,所以\(a_5\leq 5\)
那么,当我们考虑到\(a_5\)时,要讨论3中情况
那么当我们考虑\(a_3\)时,前面已经包含49了,就不需要再讨论后面有没有包含49,所以下面就是正解了——
先预处理出三个数组
假设原数n为\(\bar{b_5b_4b_3b_2b_1}\)从高位向低位扫
最后要注意细节
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <string>
#include <vector>
#define ll long long
const int N=100005;
const int M=200005;
using namespace std;
ll n,yh;
int len,flag=0,a[N];
ll f[N][3],ans=0;
int main(){
int T;
scanf("%d",&T);
while(T--){
ans=len=flag=0;yh=1;
scanf("%lld",&n);
for(int i=1;i<=100;i++){
yh*=10;
if(yh>n){
len=i;
break;
}
}
f[0][0]=1;
for(int i=1;i<=len;i++){
f[i][0]=f[i-1][0]*10;
f[i][1]=f[i-1][0]-f[i-1][2];
if(i>=2)f[i][2]=f[i-1][2]*10+f[i-1][1];
}
for(int i=1;i<=len;i++){
a[i]=n%10;
n/=10;
}
for(int i=len;i>=1;i--){
if(flag){
ans+=a[i]*f[i-1][0];
continue;
}
if(a[i]<=4){
ans+=a[i]*f[i-1][2];
}
else{
ans+=(a[i]-1)*f[i-1][2];
ans+=f[i-1][2]+f[i-1][1];
}
if(a[i]==9&&a[i+1]==4)flag=1;
}
if(flag)ans++;
printf("%lld\n",ans);
for(int i=1;i<=len;i++)f[i][0]=f[i][1]=f[i][2]=a[i]=0;
}
return 0;
}
原文:https://www.cnblogs.com/SCL123/p/11873406.html