Bzoj1111 [POI2007]四进制的天平Wag

Description

https://www.luogu.com.cn/problem/P3464

Solution

显然要转四进制。

转四进制以后,令 $f_i,g_i$ 分别问从高到低前 $i$ 为不借位/借位的最小值和方案数(结构体)。因为最小值只会从最小值转移过来,所以不用多记一维状态表示最小值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
#include<bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define maxn 50005
#define put() putchar('\n')
#define Tp template<typename T>
#define Ts template<typename T,typename... Ar>
using namespace std;
Tp void read(T &x){
int f=1;x=0;char c=getchar();
while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
while (c>='0'&&c<='9') {x=x*10+c-'0';c=getchar();}
x*=f;
}
namespace Debug{
Tp void _debug(char* f,T t){cerr<<f<<'='<<t<<endl;}
Ts void _debug(char* f,T x,Ar... y){while(*f!=',') cerr<<*f++;cerr<<'='<<x<<",";_debug(f+1,y...);}
#define gdb(...) _debug((char*)#__VA_ARGS__,__VA_ARGS__)
}using namespace Debug;
#define fi first
#define se second
#define mk make_pair
const int mod=1e9;
int power(int x,int y=mod-2) {
int sum=1;
while (y) {
if (y&1) sum=sum*x%mod;
x=x*x%mod;y>>=1;
}
return sum;
}
int a[maxn],len,c[maxn],n;
void rd(void) {
int i;string s;
cin>>s;len=s.size();
for (i=0;i<len;i++) a[i]=s[i]-'0';
reverse(a,a+len);
}
int Mod4() {
int i,res=0,t;
for (i=len-1;i>=0;i--) t=res,res=(res*10+a[i])%4,a[i]=(a[i]+t*10)/4;
while (len&&a[len-1]==0) len--;
return res;
}
struct node {
int x,y;
node(int a=0,int b=0) {x=a;y=b;}
node operator +(const node &tmp) const {
if (x==tmp.x) return node(x,(y+tmp.y)%mod);
else if (x<tmp.x) return node(x,y);
else return tmp;
}
}f[maxn],g[maxn];
signed main(void){
int i;
rd();
while (len) c[++n]=Mod4();
reverse(c+1,c+1+n);
f[0]=node(0,1);
g[0]=node(1,1);
for (i=1;i<=n;i++) {
f[i]=node(f[i-1].x+c[i],f[i-1].y)+node(g[i-1].x+4-c[i],g[i-1].y);
g[i]=node(f[i-1].x+c[i]+1,f[i-1].y)+node(g[i-1].x+3-c[i],g[i-1].y);
}
node ans=f[n];
printf("%d",ans.y);
return 0;
}