bzoj 1111 [POI2007]四进制的天平Wag 数位Dp

1111: [POI2007]四进制的天平Wag

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 302  Solved: 201
[Submit][Status][Discuss]

Description

Mary准备举办一个聚会,她准备邀请很多的人参加她的聚会。并且她准备给每位来宾准备一些金子作为礼物。为了不伤及每个人的脸面,每个人获得的金子必须相同。Mary将要用一个天平来称量出金子。她有很多的砝码,所有砝码的质量都是4的幂。Mary将金子置于左边并且将砝码置于右盘或者两个盘。她希望每次称量都使用最少的砝码。并且,他希望,每次都用不同的称量方法称出相同质量的金子。对于给定的质量n,Mary希望知道最少需要用多少个砝码可以完成称量,并且想知道用这么多个砝码一共有多少种方式进行称量。

Input

输入文件仅包含一个整数,表示Mary希望给每个人的金子的质量。(1<=n<=10^1000)

Output

输出文件仅包含一个整数,表示一共可能的称量方式对10^9的模。

Sample Input

166

Sample Output

3
样例解释
一共有三种方式称量出166。166=64+64+16+16+4+1+1。166=256-64-16-16+4+1+1。166=256-64-16-4-4-1-1。
 
 
题解:%%claris
 

首先将n转化为四进制,从低位到高位DP

f[i]表示这一位不向下一位借位

g[i]表示这一位向下一位借位,但借的那个不算在i

f[0]=0,g[0]=inf

f[i]=merge(f[i-1]+b[i],g[i-1]+b[i]+1)

g[i]=merge(f[i-1]+4-b[i],g[i-1]+3-b[i])

 1 #include<cstring>
 2 #include<cmath>
 3 #include<cstdio>
 4 #include<algorithm>
 5 #include<iostream>
 6 
 7 #define ll long long
 8 #define mod 1000000000
 9 #define N 2000
10 
11 #define Wb putchar(' ')
12 #define We putchar('
')
13 #define rg register int
14 using namespace std;
15 inline int read()
16 {
17     int x=0,f=1;char ch=getchar();
18     while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
19     while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
20     return x*f;
21 }
22 inline void write(ll x)
23 {
24     if(x<0) putchar('-'),x=-x;
25     if (x==0) putchar(48);
26     int num=0;char c[20];
27     while(x) c[++num]=(x%10)+48,x/=10;
28     while(num) putchar(c[num--]);
29 }
30 
31 int n;
32 int a[N],b[N];
33 char s[N];
34 struct Node
35 {
36     int x,y;
37     Node(){}
38     Node(int _x,int _y){x=_x,y=_y;}
39     friend Node operator+(Node x,int a){return Node(x.x+a,x.y);}
40     friend Node operator+(Node x,Node y)
41     {
42         return x.x==y.x?Node(x.x,(x.y+y.y)%mod):(x.x<y.x?x:y);
43     }
44 }f[N],g[N];
45 
46 int main()
47 {
48     scanf("%s",s);int len=strlen(s);
49     for (int i=1;i<=len;i++)
50         a[i]=s[len-i]-'0';
51     while(len)
52     {
53         a[0]=0;
54         for (rg i=len;i>=1;i--)
55             a[i-1]+=(a[i]&3)*10,a[i]>>=2;
56         for (b[++n]=a[0]/10;len&&!a[len];len--);
57     }
58     f[0]=Node(0,1),g[0]=Node(N,0),n++;
59     for (rg i=1;i<=n;i++)
60         f[i]=(f[i-1]+b[i])+(g[i-1]+(b[i]+1)),
61         g[i]=(f[i-1]+(4-b[i]))+(g[i-1]+(3-b[i]));
62     write(f[n].y);
63 }
原文地址:https://www.cnblogs.com/fengzhiyuan/p/8982429.html