HDU 5898 odd-even number
阿新 • • 發佈:2018-09-27
n) return out freopen pri inline 數位dp input pre
初稿
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn=30; ll OddNormal[maxn],EvenNormal[maxn],OddOdd[maxn],EvenEven[maxn],normal[maxn]; int a[maxn],len; ll five[maxn]; void init() { five[0]=1;for(int i=1;i<20;++i)five[i]=5*five[i-1]; OddNormal[0]=EvenNormal[0]=1; for(int n=1;n<20;++n) { OddNormal[n]=EvenNormal[n]=0; for(int i=2;i<=n/2*2;i=i+2)OddNormal[n]=OddNormal[n]+five[i]*EvenNormal[n-i]; for(int i=1;i<(n+1)/2*2;i=i+2)EvenNormal[n]=EvenNormal[n]+five[i]*OddNormal[n-i]; } for(int n=1;n<20;++n) { OddOdd[n]=EvenEven[n]=0; for(int i=2;i<=n/2*2;i=i+2)EvenEven[n]=EvenEven[n]+five[i]*OddNormal[n-i]; for(int i=1;i<(n+1)/2*2;i=i+2)OddOdd[n]=OddOdd[n]+five[i]*EvenNormal[n-i]; } normal[1]=5; for(int n=2;n<20;++n) { normal[n]=5*OddOdd[n-1]+4*EvenEven[n-1]+4*OddNormal[n-1]; normal[n]=normal[n]+normal[n-1]; } } inline int countodd(int x) { return x/2; } inline int counteven(int x) { if(x==0)return 0; return (x-1)/2+1; } ll calc() { if(len==1)return counteven(a[1]+1); ll ret=normal[len-1]+countodd(a[len])*OddOdd[len-1]+(counteven(a[len])-1)*(OddNormal[len-1]+EvenEven[len-1]); int cnt=1; for(int i=len-1;i>0;--i) { if(cnt&1) { if(a[i+1]&1) { if(i==1)ret=ret+countodd(a[1]+1); else ret=ret+countodd(a[i])*(EvenNormal[i-1]+OddNormal[i-1]); if(a[i]%2==0)break; } else { if(i==1)break; ret=ret+countodd(a[i])*OddOdd[i-1]+counteven(a[i])*EvenNormal[i-1]; } } else { if(a[i+1]&1) { if(i==1)ret=ret+counteven(a[1]+1); else ret=ret+countodd(a[i])*OddOdd[i-1]+counteven(a[i])*(OddNormal[i-1]+EvenEven[i-1]); } else { if(i==1)ret=ret+counteven(a[1]+1); else ret=ret+counteven(a[i])*(OddNormal[i-1]+EvenEven[i-1]); if(a[i]&1)break; } } if(a[i]%2==a[i+1]%2)cnt++; else cnt=1; } return ret; } int f(ll x) { len=0; while(x) { a[++len]=x%10; x=x/10; } return 0; } int main() { //freopen("Input.txt","r",stdin); init(); ll l,r,ansl,ansr; int t;scanf("%d",&t); for(int Case=1;Case<=t;++Case) { scanf("%I64d%I64d",&l,&r); ansl=ansr=0; f(r);ansr=calc(); //printf("ansr=%I64d\n",ansr); if(l==1)ansl=1; else{f(l-1);ansl=calc();} //printf("ansl=%I64d\n",ansl); printf("Case #%d: %I64d\n",Case,ansr-ansl); } }
參考網上代碼學習數位dp的代碼
#include <bits/stdc++.h> using namespace std; typedef long long ll; #define ms(s,a) memset(s,a,sizeof(s)) #define debug(x) cout<<"< "#x" = "<<x<<" >\n" int len,a[20]; ll dp[20][20][2][2];//TODO ll dfs(int pos,int cnt,bool odd,bool lim,bool zero) { if(!pos)return odd^(cnt&1); if(!lim&&dp[pos][cnt][odd][zero]!=-1)return dp[pos][cnt][odd][zero]; ll ret=0; int _max=lim?a[pos]:9; for(int i=0;i<=_max;++i) { if(zero) { if(i==0)ret+=dfs(pos-1,1,0,0,1); else ret+=dfs(pos-1,1,i&1,lim&&i==_max,0); } else { if(odd==(i&1))ret+=dfs(pos-1,cnt+1,i&1,lim&&i==_max,0); else { if(odd==(cnt&1))continue; ret+=dfs(pos-1,1,i&1,lim&&i==_max,0); } } } if(!lim)dp[pos][cnt][odd][zero]=ret; return ret; } ll calc(ll x) { if(x==0)return 1; len=0; while(x) { a[++len]=x%10; x/=10; } return dfs(len,0,0,1,1);//check it later! } int main() { //freopen("Input.txt","r",stdin); ms(dp,-1); int t;scanf("%d",&t); ll l,r; for(int Case=1;Case<=t;++Case) { scanf("%I64d%I64d",&l,&r); printf("Case #%d: %I64d\n",Case,calc(r)-calc(l-1)); } }
HDU 5898 odd-even number