規律:
首先枚舉個位,十位,百位…,然後對於每一位,作爲數字d的時候,包含的數字有多少個,分爲這個數的左右2端。
比如12345,要求d=4有多少個,對於十位,這一位取4,分成12300和45來看,對於12300,十位取4,其左邊是有123種情況,右邊有10種,所以總數就是1230,然後對於45,取4的情況有6種。然後對於百位也同樣道理。
code(以7爲例)
#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
const int man = 2e5+10;
#define IOS ios::sync_with_stdio(0)
#define ull unsigned ll
#define uint unsigned
#define pai pair<int,int>
#define pal pair<ll,ll>
#define IT iterator
#define pb push_back
#define fi first
#define se second
#define For(i,j,k) for (int i=(int)(j);i<=(int)(k);++i)
#define Rep(i,j,k) for (int i=(int)(j);i>=(int)(k);--i)
#define endl '\n'
#define ll long long
const ll mod = 1e9+7;
char str[man];
int fac[man],s[man];
signed main() {
#ifndef ONLINE_JUDGE
//freopen("in.txt", "r", stdin);
//freopen("out.txt","w",stdout);
#endif
int t;
scanf("%d",&t);
fac[0] = 1;
For(i,1,man-1)fac[i] = 1ll * fac[i-1] * 10 % mod;//處理10^i
while(t--){
scanf("%s",str+1);
int n = strlen(str+1);
For(i,1,n)s[i] = (10ll * s[i-1] + (str[i]-'0'))%mod;//計算前綴對mod取模
ll ans = 0,tp = 0;
Rep(i,n,1){
ans = (ans + 1ll * s[i-1] * fac[n-i]% mod )%mod;//計算左右總的個數
if(str[i]=='7')ans = (ans + tp + 1)%mod;//對於後一部分的計算
else if(str[i]>'7')ans = (ans + fac[n-i])%mod;
tp = (tp + 1ll*(str[i]-'0')*fac[n-i])%mod;
}
printf("%d\n",ans);
}
return 0;
}
數位dp
維護爲d(0~9)的個數和總的個數,當爲7的時候,直接把之前總的個數加到d的個數上。記憶化一下
以7位例
落谷P2602
#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
const int man = 2e5+10;
#define IOS ios::sync_with_stdio(0)
#define ull unsigned ll
#define uint unsigned
#define pai pair<int,int>
#define pal pair<ll,ll>
#define IT iterator
#define pb push_back
#define fi first
#define se second
#define For(i,j,k) for (int i=(int)(j);i<=(int)(k);++i)
#define Rep(i,j,k) for (int i=(int)(j);i>=(int)(k);--i)
#define endl '\n'
#define ll long long
const ll mod = 1e9+7;
int str[man];
int n;
pal dp[man];
template<typename t1,typename t2>
const pair<t1,t2> operator + (const pair<t1,t2> &a,const pair<t1,t2> &b){
return {a.first + b.first,a.second +b.second};
}
int d;
pal dfs(int pos,bool limit,bool lead){
if(pos==0)return {0,1};
pal &x = dp[pos];
if(!limit&&!lead&&x.first!=-1)return x;
int up = limit ? str[pos] : 9;
pal ans = {0,0};
for(int i = 0;i <= up;++i){
pal tp = dfs(pos-1,limit&&i==up,lead&&i==0);
ans = ans + tp;
if(lead&&i==0)continue;//判斷前導0,如果有前導0並且當前爲0,不統計當前位的答案。
//如果有前導0,但i不等於0,該答案還是要統計,無前導0,i等於0,依舊統計答案。
if(i==d)ans.first += tp.second;
}
if(!limit&&x.first==-1&&!lead)x = ans;
return ans;
}
ll slove(ll x){
int pos = 0;
while(x){
str[++pos] = x % 10;
x /= 10;
}
return dfs(pos,1,1).first;
}
int main() {
#ifndef ONLINE_JUDGE
//freopen("in.txt", "r", stdin);
//freopen("out.txt","w",stdout);
#endif
int t;
for(int i = 0;i < man;++i)dp[i] = {-1,0};
ll a,b;
cin >> a >> b;
for(int i = 0;i <= 9;++i){
d = i;
printf("%lld ",slove(b)-slove(a-1));
}printf("\n");
return 0;
}