spoj 10606 Balanced Numbers 11维数位dp,状压,奇观

题意

求[l,r]区间内所有奇数数字都出现了偶数次,偶数都出现了奇数次的数字个数.没有出现过的数字不算.

奇观! 11 11 维数位 d p dp !

本来这题可以用状压写的.不过我为了观赏效果开了 11 11 维的 d p dp 数组.
d p [ n o w ] [ c 0 ] [ c 1 ] [ c 2 ] [ c 3 ] [ c 4 ] [ c 5 ] [ c 6 ] [ c 7 ] [ c 8 ] [ c 9 ] dp[now][c0][c1][c2][c3][c4][c5][c6][c7][c8][c9] 表示处理到第 n o w now 位,对于 0 9 0\to9 来说, 2 2 表示没有出现过, 1 1 表示出现奇数次, 0 0 表示出现偶数次的数字个数.
因为数据范围 1 0 19 10^{19} ,我自己认为要开unsigned long long.
不过这代码跑得倒是快,0ms就过去了.

#include<bits/stdc++.h> //Ithea Myse Valgulious
namespace chtholly{
typedef long long ll;
#define re0 register int
#define rec register char
#define rel register ll
#define gc getchar
#define pc putchar
#define p32 pc(' ')
#define pl puts("")
/*By Citrus*/
inline int read(){
  int x=0,f=1;char c=gc();
  for (;!isdigit(c);c=gc()) f^=c=='-';
  for (;isdigit(c);c=gc()) x=(x<<3)+(x<<1)+(c^'0');
  return f?x:-x;
  }
template <typename mitsuha>
inline bool read(mitsuha &x){
  x=0;int f=1;char c=gc();
  for (;!isdigit(c)&&~c;c=gc()) f^=c=='-';
  if (!~c) return 0;
  for (;isdigit(c);c=gc()) x=(x<<3)+(x<<1)+(c^'0');
  return x=f?x:-x,1;
  }
template <typename mitsuha>
inline int write(mitsuha x){
  if (!x) return 0&pc(48);
  if (x<0) x=-x,pc('-');
  int bit[20],i,p=0;
  for (;x;x/=10) bit[++p]=x%10;
  for (i=p;i;--i) pc(bit[i]+48);
  return 0;
  }
inline char fuhao(){
  char c=gc();
  for (;isspace(c);c=gc());
  return c;
  }
}using namespace chtholly;
using namespace std;
typedef unsigned long long ull;
ull dp[50][3][3][3][3][3][3][3][3][3][3]; // 规模看起来十分庞大的dp数组
int bit[50];

ull dfs(int now,int c0,int c1,int c2,int c3,int c4,int c5,int c6,int c7,int c8,int c9,int lim,int lz){ // 当前枚举到的位置,0-9的个数,是否有最大位限制,否是有前导0.
if (!now) return c0&&c1^1&&c2&&c3^1&&c4&&c5^1&&c6&&c7^1&&c8&&c9^1; // 当枚举到最后的时候判断偶数出现奇数次,也就是相对应的c不为0,奇数相对应的c不为1. 
if (!lim&&lz&&~dp[now][c0][c1][c2][c3][c4][c5][c6][c7][c8][c9]) return dp[now][c0][c1][c2][c3][c4][c5][c6][c7][c8][c9];
ull llx=0; int i,da=lim?bit[now]:9;
for (i=0;i<=da;++i){ // 对于当前位枚举的每一个数都特判.
  switch(i){
    case 0: llx+=dfs(now-1,lz?c0==2?1:!c0:c0,c1,c2,c3,c4,c5,c6,c7,c8,c9,lim&&i==da,lz); break; 
    /*只有判0的时候需要注意前导0,其他数都没什么区别.*/
	case 1: llx+=dfs(now-1,c0,c1==2?1:!c1,c2,c3,c4,c5,c6,c7,c8,c9,lim&&i==da,1); break;
	case 2: llx+=dfs(now-1,c0,c1,c2==2?1:!c2,c3,c4,c5,c6,c7,c8,c9,lim&&i==da,1); break;
	case 3: llx+=dfs(now-1,c0,c1,c2,c3==2?1:!c3,c4,c5,c6,c7,c8,c9,lim&&i==da,1); break;
	case 4: llx+=dfs(now-1,c0,c1,c2,c3,c4==2?1:!c4,c5,c6,c7,c8,c9,lim&&i==da,1); break;
	case 5: llx+=dfs(now-1,c0,c1,c2,c3,c4,c5==2?1:!c5,c6,c7,c8,c9,lim&&i==da,1); break;
	case 6: llx+=dfs(now-1,c0,c1,c2,c3,c4,c5,c6==2?1:!c6,c7,c8,c9,lim&&i==da,1); break;
    case 7: llx+=dfs(now-1,c0,c1,c2,c3,c4,c5,c6,c7==2?1:!c7,c8,c9,lim&&i==da,1); break;
    case 8: llx+=dfs(now-1,c0,c1,c2,c3,c4,c5,c6,c7,c8==2?1:!c8,c9,lim&&i==da,1); break;
    case 9: llx+=dfs(now-1,c0,c1,c2,c3,c4,c5,c6,c7,c8,c9==2?1:!c9,lim&&i==da,1); break;
	}
  }
/*当前枚举的数的cnt为2,变成1;否则变成!cnt,即奇数变偶数,偶数变奇数.*/
return lim?llx:dp[now][c0][c1][c2][c3][c4][c5][c6][c7][c8][c9]=llx;
}

ull get(ull x){
for (*bit=0;x;x/=10) bit[++*bit]=x%10;
return dfs(*bit,2,2,2,2,2,2,2,2,2,2,1,0);
}

int main(){
memset(dp,-1,sizeof dp);
for (int t=read();t--;){
  ull l,r; read(l),read(r);
  write(get(r)-get(l-1)),pl;
  }
}

猜你喜欢

转载自blog.csdn.net/qq_31908675/article/details/82901577
今日推荐