zoukankan      html  css  js  c++  java
  • [POI2007]四进制的天平Wag

    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],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]);
    (注:借到的一位不算在当前第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('
    ');
    	}
    }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
    ",f[tot].y);
    	return 0;
    }
    
  • 相关阅读:
    pureftp 超时 mlsd
    安卓相机调用适配
    解决多个界面重复共用同一组数据导致数据同步改变(实现数据的完全深拷贝)
    PHP反射API的使用、体会、说明
    c冒泡排序
    iOS开发常用的第三方类库
    修改按钮上图片的大小-iOS
    获取手机通讯录--ios
    根据搜素的字符串改变label包含该字符串的文字
    cell点击按钮崩的一种情况
  • 原文地址:https://www.cnblogs.com/Wolfycz/p/8945344.html
Copyright © 2011-2022 走看看