Balanced Numbers(数位+状压)

题意:求给定区间,一个数的数位上每个奇数出现偶数次,每个偶数出现奇数次,这样数的个数

分析:先考虑状态,但总是想不全,所以要把状态压缩一下,用三进制,0 该数不放  1 放了奇数次 2放了偶数次

dp[i][j] 长度为i 状态是j的数字个数,需要前导0判断,前导0不能计入偶数出现的次数。

#include <map>

#include <set>

#include <list>

#include <cmath>

#include <queue>

#include <stack>

#include <cstdio>

#include <vector>

#include <string>

#include <cctype>

#include <complex>

#include <cassert>

#include <utility>

#include <cstring>

#include <cstdlib>

#include <iostream>

#include <algorithm>

using namespace std;

typedef pair<int,int> PII;

typedef long long ll;

#define lson l,m,rt<<1

#define pi acos(-1.0)

#define rson m+1,r,rt<<11

#define All 1,N,1

#define read freopen("in.txt", "r", stdin)

const ll  INFll = 0x3f3f3f3f3f3f3f3fLL;

const int INF= 0x7ffffff;

const int mod =  1000000007;

ll dp[25][100000],a,b;

int bit[25],cas[15];
//化三进制
void get(int x) { for(int i=0; i<10; ++i) { cas[i]=x%3; x/=3; } }
//状态改变
int change(int x,int b) { get(x); if(cas[b]==0) cas[b]=1; else if(cas[b]==1) cas[b]=2; else cas[b]=1; int s=0,tmp=1; for(int i=0; i<10; ++i) { s+=cas[i]*tmp; tmp*=3; } return s; }
//判断符合条件
int judge(int s) { get(s); for(int i=0; i<10; ++i) { if(i%2&&cas[i]==1)return 0; if(i%2==0&&cas[i]==2)return 0; } return 1; } ll dfs(int i,int j,int f,int e) { if(i==0)return judge(j); if(!e&&dp[i][j]!=-1)return dp[i][j]; int u=e?bit[i]:9; ll num=0; for(int v=0; v<=u; ++v) { if(f&&v==0) num+=dfs(i-1,0,1,e&&(v==u)); else { num+=dfs(i-1,change(j,v),0,e&&(v==u)); } } if(!e)dp[i][j]=num; return num; } ll solve(ll x) { int len=0; while(x) { bit[++len]=x%10; x/=10; } return dfs(len,0,1,1); } int main() { int t; scanf("%d",&t); memset(dp,-1,sizeof(dp)); while(t--) { scanf("%I64d%I64d",&a,&b); printf("%I64d\n",solve(b)-solve(a-1)); } return 0; }

 

你可能感兴趣的:(number)