您的位置:首页 > 其它

SPOJ - BALNUM 数位dp

2017-09-01 15:18 316 查看
题意:求某一区间内的平衡数个数(指一个数,其中出现过的数,如果是偶数,那么必须出现奇数次,反之偶数次)

题解:用三进制来枚举(0到9)所有情况,0代表没有出现,1代表出现奇数次,2代表出现偶数次dp【i】【j】i代表位数,j代表状态,在记忆化搜索的时候要记录0是否出现过

(因为之前很少写3进制的状态,写的大多数是2进制的,所以很不熟练,还是要多练,刚开始是把题意理解错了,以为是所有的奇数出现偶数次 这样,所以搞了半天也不对)

#include<bits/stdc++.h>
#define C 0.5772156649
#define pi acos(-1.0)
#define ll long long
#define mod 1000000007
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1
#pragma comment(linker, "/STACK:1024000000,1024000000")

using namespace std;

const double g=10.0,eps=1e-7;
const int N=20+10,maxn=60000+10,inf=0x3f3f3f;

int digit
;
ll dp
[maxn];
bool check(int s)
{
int num[20];
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 0;
if(i%2==1&&num[i]==1)return 0;
}
}
return 1;
}
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 ans=0;
for(int i=9;i>=0;i--)
{
ans*=3;
ans+=num[i];
}
return ans;
}
ll dfs(int len,int s,bool ok,bool fp)
{
if(!len)
{
if(check(s))return 1;
return 0;
}
if(!fp&&dp[len][s]!=-1)return dp[len][s];
ll ans=0,fpmax=fp ? digit[len] : 9;
for(int i=0;i<=fpmax;i++)
{
ans+=dfs(len-1,(ok&&i==0)?0:getnews(i,s),ok&&i==0,fp&&i==fpmax);
}
if(!fp)dp[len][s]=ans;
return ans;
}
ll solve(ll x)
{
int len=0;
while(x)
{
digit[++len]=x%10;
x/=10;
}
return dfs(len,0,1,1);
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int t;
cin>>t;
memset(dp,-1,sizeof dp);
while(t--)
{
ll l,r;
cin>>l>>r;
cout<<solve(r)-solve(l-1)<<endl;
}
return 0;
}
/********************

********************/


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: