SPOJ 10606. Balanced Numbers (数位DP)
题目链接:http://www.spoj.com/problems/BALNUM/
这题要求出现的数字,偶数出现奇数次,奇数出现偶数次。
用三进制表示0~9的状态
//============================================================================ // Name : SPOJ.cpp // Author : // Version : // Copyright : Your copyright notice // Description : Hello World in C++, Ansi-style //============================================================================ #include <iostream> #include <stdio.h> #include <string.h> #include <algorithm> using namespace std; long long dp[20][60000]; //3进制表示数字0~9的出现情况,0表示没有出现,1表示奇数次,2表示偶数次 int bit[20]; bool check(int s) { int num[10]; for(int i=0;i<10;i++) { num[i]=s%3; s/=3; } for(int i=0;i<10;i++) if(num[i]!=0) { if(i%2==0 && num[i]==2)return false; if(i%2==1 && num[i]==1)return false; } return true; } int getnews(int x,int s) { int num[10]; for(int i=0;i<10;i++) { num[i]=s%3; s/=3; } if(num[x]==0)num[x]=1; else num[x]=3-num[x]; int news=0; for(int i=9;i>=0;i--) { news*=3; news+=num[i]; } return news; } long long dfs(int pos,int s,bool flag,bool z) { if(pos==-1)return check(s); if(!flag && dp[pos][s]!=-1) return dp[pos][s]; long long ans=0; int end=flag?bit[pos]:9; for(int i=0;i<=end;i++) ans+=dfs(pos-1,(z&&i==0)?0:getnews(i,s),flag&&i==end,z&&i==0); if(!flag)dp[pos][s]=ans; return ans; } long long calc(long long n) { int len=0; while(n) { bit[len++]=n%10; n/=10; } return dfs(len-1,0,1,1); } int main() { //freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout); int T; memset(dp,-1,sizeof(dp)); long long a,b; scanf("%d",&T); while(T--) { cin>>a>>b; cout<<calc(b)-calc(a-1)<<endl; } return 0; }
人一我百!人十我万!永不放弃~~~怀着自信的心,去追逐梦想