K-lucky-number

題目鏈接:K-lucky-number


因爲不是求個數,而是平方,所以我們dp方程需要維護多個值,出現次數,和,平方和。

然後每次和求個數一樣轉移即可。

相當於把每一位拆開,然後類似於秦九韶算法,從前往後維護。


AC代碼:

#pragma GCC optimize("-Ofast","-funroll-all-loops")
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int mod=1e9+7;
int a[20],l,r,k,p[20]={1};
struct node{int cnt,s1,s2;}dp[20][40];
node dfs(int pos,int s,int lim){
	if(!pos)	return {s==0,0,0};
	if(!lim&&dp[pos][s].s1!=-1)	return dp[pos][s];
	int up=lim?a[pos]:9; node res; res.cnt=res.s1=res.s2=0;
	for(int i=0;i<=up;i++){
		node tmp=dfs(pos-1,(s+i)%k,lim&&i==up);
		res.cnt=(res.cnt+tmp.cnt)%mod;
		res.s1=(res.s1+tmp.s1+tmp.cnt*i%mod*p[pos-1]%mod)%mod;
		res.s2=(res.s2+tmp.s2+tmp.cnt*i%mod*i%mod*p[pos-1]%mod*p[pos-1]%mod+
		2LL%mod*i%mod*tmp.s1%mod*p[pos-1]%mod);
	}
	if(!lim)	dp[pos][s]=res;
	return res;
}
inline int calc(int x){
	int pos=0;
	while(x)	a[++pos]=x%10,x/=10;
	return dfs(pos,0,1).s2;
}
inline void solve(){
	cin>>l>>r>>k;	memset(dp,-1,sizeof dp);
	cout<<((calc(r)-calc(l-1))%mod+mod)%mod<<endl;
}
signed main(){
	for(int i=1;i<=10;i++)	p[i]=p[i-1]*10%mod;
	int T;	cin>>T;	while(T--) solve();
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章