P3464 [POI2007] WAG-Quaternary Balance 题解
题意
给定一个数
思路
首先看到这道题的数据范围
最重要的还是 DP 方程的设计了。题目说可以在两数之间做加减运算,所以必须考虑一个很重要的东西——借位。因为减法运算的过程中会出现向高位借位的情况。举个例子:
设
-
f_{i} = (f_{i - 1} + b_{i}) + (g_{i - 1} + b_{i} + 1) -
g_{i} = (f_{i - 1} + 4 - b_{i}) + (g_{i - 1} + 3 - b_{i} )
注意:这里的 f 和 g 均是结构体数组,加号的意义在结构体内经过了重定义,具体意义详见代码。
Code
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define ls id << 1
#define rs id << 1 | 1
#define inf 0x3f3f3f3f
typedef pair <int,int> pii;
const int MAXN = 5e3 + 10;
const int mod = 1e9;
int a[MAXN],cnt,b[MAXN],n;
char c[MAXN];
struct Node
{
int x,y;Node(){};
//x为数的个数,y为方案数
Node(int a,int b){x = a,y = b;}
inline Node operator + (int a){return Node(x + a,y);}
//结构体加普通数:数的个数相加,方案数不变
inline Node operator + (Node b){return x == b.x ? Node(x,(y + b.y) % mod) : (x < b.x ? Node(x,y) : b);}
//结构体加结构体:如果数的个数相等,则方案数相加;否则选数的个数较少的情况时的方案数。
}f[MAXN],g[MAXN];
signed main()
{
cin >> c + 1;
int len = strlen(c + 1);
for(int i = len;i >= 1;i--) a[i] = c[len - i + 1] - '0';
while(len)
{
a[0] = 0;
for(int i = len;i >= 1;i--)
{
a[i - 1] += ((a[i] % 4) * 10);
a[i] = (a[i] - a[i] % 4) / 4;
}
b[++cnt] = a[0] / 10;
if(a[len] == 0) len--;
}
cnt++;
f[0] = Node(0,1),g[0] = Node(MAXN,0);
for(int i = 1;i <= cnt;i++)
{
f[i] = (f[i - 1] + b[i]) + (g[i - 1] + b[i] + 1);
g[i] = (f[i - 1] + (4 - b[i])) + (g[i - 1] + (3 - b[i]));
}
cout << f[cnt].y;
return 0;
}