首页 > 代码库 > HDU 5808[数位dp]
HDU 5808[数位dp]
/*题意:给你l和r,范围9e18,求l到r闭区间有多少个数字满足,连续的奇数的个数都为偶数,连续的偶数的个数都为奇数。例如33433符合要求,44不符合要求。不能含有前导零。思路:队友说是数位dp...我都反映不过来。知道是数位dp以后,思路就显而易见了。dp的方法是最后一位的性质,是偶数还是奇数,是连续的第偶数个还是第奇数个。所以一共只有四种状态,而题目中最多19位数字...用了以上的方法,我们可以轻易解决有n为数字的符合要求的数字的个数。问题是如何考虑边界条件。所以我们可以先判断l和r有多少位。然后提前打表,中间的位数直接加到答案上来就好。现在我们讨论跟l和r位数相同的在l到r范围内的,即大于等于l,小于等于r的个数。假如l和r位数相同,那么我们可以用小于等于r的减去小于等于l的,然后特判l是不是。位数不同,可以直接求和l位数相同的,大于等于l的加上和r位数相同的小于等于r的。所以现在问题转化为,位数确定的情况下,小于等于或者大于等于某个数的符合条件数的个数有多少。类似dfs,依次讨论前几位大于等于某位或者小于等于某位有多少个...(这个大概是数位dp的核心?)【简单说一下,第i次统计的数目是,假如第i位大于边界值,而前i-1位等于边界值的符合要求的数字的数目,这样一直统计到i+1...】*/#include<bits/stdc++.h>using namespace std;bool panduan(unsigned long long num){ int curr=0; int len=0; while(num) { int temp=num%10; if(curr==0) { if(temp%2) curr=1; else curr=2; len=1; } else { if(curr==1) { if(temp%2) len++; else { if(len%2) return false; len=1; curr=2; } } else { if(temp%2==0) len++; else { if(len%2==0) return false; len=1; curr=1; } } } num/=10; } if((curr==1)&&(len%2==0)) return true; if((curr==2)&&(len%2==1)) return true; return false;}int get_wei(unsigned long long t){ int rel=0; while(t>0){ rel++; t/=10; } return rel;}unsigned long long dp[20][4];unsigned long long biao[30];void dabiao(){ for(int i=1;i<=19;i++){ memset(dp,0,sizeof(dp)); for(int j=1;j<=i;j++){ if(j==1){ dp[j][0]+=4; dp[j][2]+=5; } dp[j][0]+=(dp[j-1][1]+dp[j-1][3])*5; dp[j][1]+=dp[j-1][0]*5; dp[j][2]+=(dp[j-1][0]+dp[j-1][3])*5; dp[j][3]+=dp[j-1][2]*5; } biao[i]=dp[i][0]+dp[i][3]; }}int fenjie[30];unsigned long long dayudengyu(unsigned long long l){ unsigned long long rel=0; unsigned long long ll=l; int num=0; while(ll>0){ fenjie[num++]=ll%10; ll/=10; } for(int i=0;i<num/2;i++){ swap(fenjie[i],fenjie[num-i-1]); } memset(dp,0,sizeof(dp)); for(int i=0;i<num;i++){ for(int j=i;j<num;j++){ if(j==i){ if(fenjie[i]&1){ if(j==0){ dp[j][0]=dp[j][2]=(10-fenjie[i])/2; } else{ int ttt=(10-fenjie[i])/2; dp[j][0]=(dp[j-1][1]+dp[j-1][3])*ttt; dp[j][1]=dp[j-1][0]*ttt; dp[j][2]=(dp[j-1][0]+dp[j-1][3])*ttt; dp[j][3]=dp[j-1][2]*ttt; } } else{ if(j==0){ dp[j][0]=(10-fenjie[i])/2-1; dp[j][2]=(10-fenjie[i])/2; } else{ int ttt=(10-fenjie[i])/2; dp[j][0]=(dp[j-1][1]+dp[j-1][3])*(ttt-1); dp[j][1]=dp[j-1][0]*(ttt-1); dp[j][2]=(dp[j-1][0]+dp[j-1][3])*ttt; dp[j][3]=dp[j-1][2]*ttt; } } } else{ dp[j][0]=(dp[j-1][1]+dp[j-1][3])*5; dp[j][1]=dp[j-1][0]*5; dp[j][2]=(dp[j-1][0]+dp[j-1][3])*5; dp[j][3]=dp[j-1][2]*5; } } rel+=dp[num-1][0]+dp[num-1][3]; memset(dp,0,sizeof(dp)); for(int j=0;j<=i;j++){ if(j==0){ if(fenjie[j]&1)dp[j][2]=1; else dp[j][0]=1; } else{ if(fenjie[j]&1){ dp[j][2]=(dp[j-1][0]+dp[j-1][3]); dp[j][3]=dp[j-1][2]; } else{ dp[j][0]=(dp[j-1][1]+dp[j-1][3]); dp[j][1]=dp[j-1][0]; } } } } return rel+dp[num-1][0]+dp[num-1][3];}unsigned long long xiaoyudengyu(unsigned long long l){ unsigned long long rel=0; unsigned long long ll=l; int num=0; while(ll>0){ fenjie[num++]=ll%10; ll/=10; } for(int i=0;i<num/2;i++){ swap(fenjie[i],fenjie[num-i-1]); } memset(dp,0,sizeof(dp)); for(int i=0;i<num;i++){ for(int j=i;j<num;j++){ if(j==i){ if(fenjie[i]&1){ if(j==0){ dp[j][0]=fenjie[i]/2; dp[j][2]=fenjie[i]/2; } else{ unsigned long long ttt=(fenjie[i])/2+1; unsigned long long tt=fenjie[i]/2; dp[j][0]=(dp[j-1][1]+dp[j-1][3])*ttt; dp[j][1]=dp[j-1][0]*ttt; dp[j][2]=(dp[j-1][0]+dp[j-1][3])*tt; dp[j][3]=dp[j-1][2]*tt; } } else{ if(j==0){ dp[j][0]=max(fenjie[i]/2-1,0); dp[j][2]=(fenjie[i])/2; } else{ int ttt=max(0,fenjie[i]/2); int tt=fenjie[i]/2; dp[j][0]=(dp[j-1][1]+dp[j-1][3])*(ttt); dp[j][1]=dp[j-1][0]*(ttt); dp[j][2]=(dp[j-1][0]+dp[j-1][3])*(tt); dp[j][3]=dp[j-1][2]*tt; } } } else{ dp[j][0]=(dp[j-1][1]+dp[j-1][3])*5; dp[j][1]=dp[j-1][0]*5; dp[j][2]=(dp[j-1][0]+dp[j-1][3])*5; dp[j][3]=dp[j-1][2]*5; } } rel+=dp[num-1][0]+dp[num-1][3]; //cout << rel << endl; memset(dp,0,sizeof(dp)); for(int j=0;j<=i;j++){ if(j==0){ if(fenjie[j]&1)dp[j][2]=1; else dp[j][0]=1; } else{ if(fenjie[j]&1){ dp[j][2]=(dp[j-1][0]+dp[j-1][3]); dp[j][3]=dp[j-1][2]; } else{ dp[j][0]=(dp[j-1][1]+dp[j-1][3]); dp[j][1]=dp[j-1][0]; } } } } return rel+dp[num-1][0]+dp[num-1][3];}int main(){ int a; dabiao(); int cas=0; scanf("%d",&a); while(a--){ cas++; unsigned long long l,r,ll,rr; unsigned long long rel=0; scanf("%llu%llu",&l,&r); int st=get_wei(l); int ed=get_wei(r); for(int i=st+1;i<ed;i++){ rel+=biao[i]; } if(st==ed){ rel+=xiaoyudengyu(r); rel+=panduan(l); rel-=xiaoyudengyu(l); } else{ rel+=dayudengyu(l); rel+=xiaoyudengyu(r); } printf("Case #%d: ",cas); printf("%llu\n",rel); }}
HDU 5808[数位dp]
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。