CodeForces - 628D Magic Numbers(数位dp)
題目鏈接:點(diǎn)擊查看
題目大意:首先規(guī)定一個(gè)不含前導(dǎo)零的數(shù)字如果滿足:
則稱該數(shù)字為 d?magicd-magicd?magic 數(shù)字?,F(xiàn)在給出一個(gè)區(qū)間 [l,r][ l , r ][l,r] ,問(wèn)區(qū)間內(nèi)有多少個(gè)可以整除 mmm 的 d?magicd-magicd?magic 數(shù)字,lll 和 rrr 同階且 l,r∈[1,102000]l,r \in [ 1 , 10^{2000} ]l,r∈[1,102000]
題目分析:數(shù)位 dp,因?yàn)轭}目中規(guī)定了 lll 和 rrr 同階,所以降低了些許難度(不用考慮前導(dǎo)零的影響了),所以比較顯然的一個(gè)狀態(tài)就是 dppos,sumdp_{pos,sum}dppos,sum?為當(dāng)前數(shù)位為 pospospos,對(duì) mmm 取余后的結(jié)果為 sumsumsum 時(shí)的 d?magicd-magicd?magic 數(shù)字的個(gè)數(shù),不需要考慮前導(dǎo)零的話直接帶上一個(gè) limitlimitlimit 去轉(zhuǎn)移就好了
那么考慮一下如果 lll 和 rrr 不同階,也就是需要考慮前導(dǎo)零的話該如何去做呢?其實(shí)加上兩維即可:dppos,sum,lead,evendp_{pos,sum,lead,even}dppos,sum,lead,even?,新增的 leadleadlead 意義為是否含有前導(dǎo)零,eveneveneven 實(shí)質(zhì)上是調(diào)節(jié)奇偶的,因?yàn)榍皩?dǎo)零的個(gè)數(shù)會(huì)影響最高位的奇偶性,所以需要一個(gè)變量調(diào)節(jié)一下,關(guān)于轉(zhuǎn)移的話對(duì)前導(dǎo)零實(shí)現(xiàn)一下細(xì)節(jié)就好了
代碼:
不含前導(dǎo)零
含有前導(dǎo)零
// #pragma GCC optimize(2) // #pragma GCC optimize("Ofast","inline","-ffast-math") // #pragma GCC target("avx,sse2,sse3,sse4,mmx") #include<iostream> #include<cstdio> #include<string> #include<ctime> #include<cmath> #include<cstring> #include<algorithm> #include<stack> #include<climits> #include<queue> #include<map> #include<set> #include<sstream> #include<cassert> #include<bitset> #include<unordered_map> using namespace std;typedef long long LL;typedef unsigned long long ull;const int inf=0x3f3f3f3f;const int N=2100;const int mod=1e9+7;LL dp[N][N][2][2];//dp[pos][sum][lead][even]string b;int m,d;LL dfs(int pos,int sum,int limit,int lead,int even)//當(dāng)前的位置,%m的余數(shù) {if(pos==(int)b.size())return sum%m==0;if(!limit&&dp[pos][sum][lead][even]!=-1)return dp[pos][sum][lead][even];int up=limit?b[pos]-'0':9;LL ans=0;for(int i=0;i<=up;i++){if(((pos-even)&1)&&i!=d)//偶數(shù)位置必須為dcontinue;if(!((pos-even)&1)&&i==d)//奇數(shù)位置不能為dcontinue;if(lead&&i==0)//前導(dǎo)零ans=(ans+dfs(pos+1,(sum*10+i)%m,limit&&i==up,true,even^1))%mod;elseans=(ans+dfs(pos+1,(sum*10+i)%m,limit&&i==up,false,even))%mod;}if(!limit)dp[pos][sum][lead][even]=ans;return ans; }LL solve(string num) {b=num;return dfs(0,0,1,1,0); }int main() { #ifndef ONLINE_JUDGE // freopen("data.in.txt","r",stdin); // freopen("data.out.txt","w",stdout); #endif // ios::sync_with_stdio(false);memset(dp,-1,sizeof(dp));scanf("%d%d",&m,&d);string a,b;cin>>a>>b;auto check=[&](string num){int sum=0;for(int i=0;i<(int)a.size();i++){sum=(sum*10+a[i]-'0')%m;if(i&1)//even{if(a[i]!='0'+d)return false;}else{if(a[i]=='0'+d)return false;}}return sum==0;};printf("%I64d\n",(check(a)+solve(b)-solve(a)+mod)%mod);return 0; }總結(jié)
以上是生活随笔為你收集整理的CodeForces - 628D Magic Numbers(数位dp)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: CodeForces - 1076D E
- 下一篇: CodeForces - 1459D G