Balanced Numbers SPOJ - BALNUM

北城以北 提交于 2019-12-05 17:33:38

代码+注释

  1 //我感觉这道题最扯的就是我因为输入而TLE了半天,懵逼死了,想破脑袋也没想到因为输入TLE了半天
  2 //题意:求区间内数字满足“奇数各数出现偶数次,偶数各数出现奇数次”的数字的个数。
  3 //题解:
  4 //dp[x][y]表示长度为x的时候0~9各出现的状态情况,因为可能有未出现的情况,如果这个y用二进制
  5 //保存的话那么未出现的偶数可能会因为0而出现误判,所以应该多一个状态,就用三进制。0表示未出现,
  6 //1表示出现了奇数次,2表示出现了偶数次。
  7 //就是一道状压+数位dp,和XHXJ's LIS HDU - 4352 很相似
  8 //XHXJ's LIS HDU - 4352(这个是状压成二进制+dp):https://www.cnblogs.com/kongbursi-2292702937/p/11934243.html
  9 
 10 #include<stdio.h>
 11 #include<string.h>
 12 #include<algorithm>
 13 #include<iostream>
 14 using namespace std;
 15 const int maxn=20;
 16 const int N=1<<10;
 17 typedef long long ll;
 18 ll v[maxn],dp[maxn][60000],w[15];
 19 //ll mul(ll x, ll y) {
 20 //  ll ret = 1;
 21 //  while(y) {
 22 //    if(y & 1) ret *= x;
 23 //    x *= x;
 24 //    y >>= 1;
 25 //  }
 26 //  return ret;
 27 //}
 28 //ll update(ll i,ll s) {
 29 //  ll ts = s, ti = i;
 30 //  while(ti--) ts /= 3;
 31 //  ll bit = ts % 3;
 32 //  if(bit < 2) return s + mul(3, i);
 33 //  return s - mul(3, i);
 34 //}
 35 ll update(ll x,ll y) //更新我们压缩的状态
 36 {
 37     ll ans[maxn],len=0;
 38     memset(ans,0,sizeof(ans));
 39     while(y)
 40     {
 41         ans[len]=y%3;
 42         len++;
 43         y/=3;
 44     }
 45     if(ans[x]==0)
 46     {
 47         ans[x]=1;
 48     }
 49     else if(ans[x]==1)
 50         ans[x]=2;
 51     else ans[x]=1;
 52     len=max(x+1,len);
 53 
 54     y=0;
 55     x=1;
 56     for(ll i=0; i<len; ++i)
 57     {
 58         y+=ans[i]*x;
 59         x*=3;
 60     }
 61     return y;
 62 }
 63 bool get_num(ll x)
 64 {
 65     ll ans[maxn],len=0;
 66     memset(ans,0,sizeof(ans));
 67     while(x)
 68     {
 69         ans[len]=x%3;
 70         len++;
 71         x/=3;
 72     }
 73     bool flag=0;
 74     for(ll i=0; i<len; ++i)
 75     {
 76         if(i==0 || i%2==0)
 77         {
 78             if(ans[i]!=0 && ans[i]!=1)
 79             {
 80                 flag=1;
 81                 break;
 82             }
 83 
 84         }
 85         else
 86         {
 87             if(ans[i]!=0 && ans[i]!=2)
 88             {
 89                 flag=1;
 90                 break;
 91             }
 92 
 93         }
 94     }
 95     return flag;
 96 }
 97 ll dfs(ll pos,ll sta,bool limit,bool lead)
 98 {
 99     if(pos==-1)
100     {
101         if(!get_num(sta))
102             return 1;
103         else return 0;
104     }
105     if(!limit && dp[pos][sta]!=-1) return dp[pos][sta];
106     ll up=limit?v[pos]:9;
107     ll tmp=0;
108     for(ll i=0; i<=up; ++i)
109     {
110         if(lead && i==0)
111         {
112             tmp+=dfs(pos-1,0,limit && i==v[pos],1);
113 
114         }
115         else
116         {
117 
118             tmp+=dfs(pos-1,update(i,sta),limit && i==v[pos],0);
119 
120         }
121     }
122     if(!limit) dp[pos][sta]=tmp;
123     return tmp;
124 }
125 ll solve(ll ans)
126 {
127     ll pos=0;
128     while(ans)
129     {
130         v[pos++]=ans%10;
131         ans/=10;
132     }
133     return dfs(pos-1,0,true,1);
134 }
135 int main()
136 {
137     int t;
138     ll l,r;
139     cin>>t;
140     memset(dp,-1,sizeof(dp));
141     while(t--)
142     {
143         cin >> l >> r;
144         cout << solve(r) - solve(l-1) << endl;
145     }
146     return 0;
147 }

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!