1. 程式人生 > >[POI2007]四進制的天平Wag

[POI2007]四進制的天平Wag

sizeof fin inline opera 文件 def 十分 方式 div

Description
Mary準備舉辦一個聚會,她準備邀請很多的人參加她的聚會。並且她準備給每位來賓準備一些金子作為禮物。為了不傷及每個人的臉面,每個人獲得的金子必須相同。Mary將要用一個天平來稱量出金子。她有很多的砝碼,所有砝碼的質量都是4的冪。Mary將金子置於左邊並且將砝碼置於右盤或者兩個盤。她希望每次稱量都使用最少的砝碼。並且,他希望,每次都用不同的稱量方法稱出相同質量的金子。對於給定的質量n,Mary希望知道最少需要用多少個砝碼可以完成稱量,並且想知道用這麽多個砝碼一共有多少種方式進行稱量。

Input
輸入文件僅包含一個整數,表示Mary希望給每個人的金子的質量。(1<=n<=10^1000)

Output
輸出文件僅包含一個整數,表示一共可能的稱量方式對10^9的模。

Sample Input
166

Sample Output
3

HNIT
一共有三種方式稱量出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。

首先把n轉成4進制,然後開始從低位向高位DP。
f[i]表示不向下一位借位,g[i]表示向下一位借位,那麽轉移方程十分顯然了。
f[i]=merge(f[i-1]+T[i],g[i-1]+1+T[i]);
g[i]=mergr(f[i-1]+4-T[i],g[i-1]+3-T[i]);
(ps:借到的一位不算在當前第i位上,f[i]記錄的只是4^i,不論正負)

/*program from Wolfycz*/
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define inf 0x7f7f7f7f
using namespace std;
typedef long long ll;
typedef unsigned int ui;
typedef unsigned long long ull;
inline int read(){
    int x=0,f=1;char
ch=getchar(); for (;ch<‘0‘||ch>‘9‘;ch=getchar()) if (ch==‘-‘) f=-1; for (;ch>=‘0‘&&ch<=‘9‘;ch=getchar()) x=(x<<1)+(x<<3)+ch-‘0‘; return x*f; } inline void print(int x){ if (x>=10) print(x/10); putchar(x%10+‘0‘); } const int p=1e9; const int N=1e4; const int digit=4; const int base=1e4; char s[N+10]; struct Bignum{ int v[N+10],len; Bignum(){len=1,memset(v,0,sizeof(v));} void read(){ scanf("%s",s); int t=strlen(s),tim=1; len=(t-1)/digit+1; for (int i=0,j=t-1;i<j;i++,j--) swap(s[i],s[j]); for (int i=0;i<t;i++){ v[i/digit]+=(s[i]-‘0‘)*tim,tim*=10; if (tim==base) tim=1; } } void write(){ printf("%d",v[len-1]); for (int i=len-2;~i;i--) printf("%0*d",digit,v[i]); putchar(\n); } }A,Zero; int operator %(Bignum x,int y){ for (int i=x.len;i;i--) x.v[i-1]+=x.v[i]%y*base; return x.v[0]%y; } Bignum operator /(Bignum &x,int y){ for (int i=x.len;~i;i--) x.v[i-1]+=x.v[i]%y*base,x.v[i]/=y; while (!x.v[x.len]&&x.len) x.len--; x.len++; return x; } bool operator ==(const Bignum &x,const Bignum &y){ if (x.len!=y.len) return 0; for (int i=0;i<=x.len;i++) if (x.v[i]!=y.v[i]) return 0; return 1; } bool operator !=(const Bignum &x,const Bignum &y){return !(x==y);} struct Dp{ int x,y; Dp(){} Dp(int _x,int _y){x=_x,y=_y;} }f[N+10],g[N+10]; Dp min(const Dp &a,const Dp &b){return a.x<b.x?a:b;} Dp operator +(const Dp &a,int b){return Dp(a.x+b,a.y);} Dp operator +(const Dp &a,const Dp &b){return a.x==b.x?Dp(a.x,(a.y+b.y)%p):min(a,b);} int T[N+10]; int main(){ int tot=1; A.read(); while (A!=Zero) T[tot++]=A%4,A=A/4; f[0]=Dp(0,1),g[0]=Dp(inf,0); for (int i=1;i<=tot;i++){ f[i]=(f[i-1]+T[i])+(g[i-1]+(T[i]+1)); g[i]=(f[i-1]+(4-T[i]))+(g[i-1]+(3-T[i])); } printf("%d\n",f[tot].y); return 0; }

[POI2007]四進制的天平Wag