hdu 5787 2016多校5

来源:互联网 发布:pscs3软件百度云 编辑:程序博客网 时间:2024/05/29 06:48

题意:求出区间[L,R]任一连续k个数没有重复数字的数的个数。2<=k<=5

题解:数位dp,保存前k-1个数字的状态。

#include<sstream>#include<iostream>#include<math.h>#include<vector>#include<algorithm>#include<string.h>using namespace std;typedef long long LL;LL dp[21][161051];vector<int> str;void toString(LL x){str.clear();do{str.push_back(x%10);x/=10;}while(x);reverse(str.begin(),str.end());}LL moK[7];LL dfs(int osta,int p,int sta,int K,bool f){if(p==(int)str.size()) return 1;if(f){if(dp[p][sta]!=-1) return dp[p][sta];dp[p][sta]=0;if(sta==osta){dp[p][sta]+=dfs(osta,p+1,osta,K,true);}for(int i=0;i<10;i++){if(i==0&&sta==osta) continue;int tmp = sta;bool ok = true;for(int k=1;k<K;k++){if(tmp%11==i){ok=false;break;}tmp/=11;}if(ok){dp[p][sta]+=dfs(osta,p+1,(sta*11+i)%moK[K],K,f);}}return dp[p][sta];}else{LL ret = 0;if(sta==osta){ret += dfs(osta,p+1,osta,K,true);}for(int i=0;i<=str[p];i++){if(i==0&&sta==osta) continue;int tmp = sta;bool ok = true;for(int k=1;k<K;k++){if(tmp%11==i){ok=false;break;}tmp/=11;}if(ok&&i<str[p]){ret+=dfs(osta,p+1,(sta*11+i)%moK[K],K,true);}else if(ok){ret+=dfs(osta,p+1,(sta*11+i)%moK[K],K,false);}}return ret;}return 0;}LL coutV(LL x,int K){LL sta=0;for(int i=1;i<K;i++){sta=sta*11+10;}toString(x);memset(dp,-1,sizeof(dp));return dfs(sta,0,sta,K,false);}LL getAns(LL L,LL R,int K){return coutV(R,K)-coutV(L-1,K);}int main(){LL L,R,K;moK[0]=1;for(int i=1;i<=6;i++){moK[i]=moK[i-1]*11;}//printf("%I64d\n",moK[5]);while(scanf(" %I64d %I64d %d",&L,&R,&K)==3){printf("%I64d\n",getAns(L,R,K));fflush(stdout);}return 0;}


0 0
原创粉丝点击