牛客 吉林大学ACM集训队选拔赛 (重现赛)A 数位dp

被榜骗了 *** h题不是有手就会吗 怎么就那么点人过啊 

不过我还是补a 数位dp 很久很久以前写过 不要62 不过忘得干干净净了 

这题应该是数位dp里面最简单的那种吧 

链接:https://ac.nowcoder.com/acm/contest/5944/A
来源:牛客网
 

题目描述

One day, Ks raised a question in this contest.

How many times the digit 7\texttt{7}7 appears in the integer range of [0, n]?

The answer may be very large, please output the answer modulo 1 000 000 0071\,000\,000\,0071000000007.

输入描述:

 

First line contains an integer T (1≤T≤100)T ~ (1 \leq T \leq 100)T (1≤T≤100), indicating the count of questions.

Each of the following T lines contains one integer n (1≤n≤10100000)n ~ (1 \leq n \leq {10}^{100000})n (1≤n≤10100000).

输出描述:

Output T lines, one number per line representing the answer.
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5+10;
char a[N];
typedef long long ll;
ll dp[N],_10pow[N],c[N];
const ll mod = 1e9+7;
ll ans;
void getans(int len){
	for(int i = len; i >= 1; i--)
		c[i]=a[len-i+1]-'0';
	for(int i = len; i >= 1; i--){
		ans+=dp[i-1]*c[i]%mod;//在第i位的情况下 7出现在后面的位
		ans%=mod;
		if(7<c[i]) ans+=_10pow[i-1];//7出现在第i位
		ans%=mod;
	}
	ll now = 0;
	for(int i = 1; i <= len; i++){//当某一位是7的时候 它出现的次数就是 它的后缀部分的大小+1
		if(c[i]==7) ans=(ans+now+1)%mod;
		now=(now+c[i]*_10pow[i-1])%mod;
	}
	printf("%lld\n",ans);
}
int main(){
	int t;
	scanf("%d",&t);
	_10pow[0]=1;
	for(int i = 1; i < N; i++){
		dp[i]=((dp[i-1]*10ll%mod)+_10pow[i-1])%mod;
		_10pow[i]=_10pow[i-1]*10ll%mod;
	}
	while(t--){
		scanf("%s",a+1);
		ans=0;
		int len=strlen(a+1); 
		getans(len);	
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43824564/article/details/106747799