• 递推+高精度 UVA 10497 Sweet Child Makes Trouble(可爱的孩子惹麻烦)


    题目链接

    题意:

      n个物品全部乱序排列(都不在原来的位置)的方案数。

    思路:

      dp[i]表示i个物品都乱序排序的方案数,所以状态转移方程。考虑i-1个物品乱序,放入第i个物品一定要和i-1个的其中一个交换位置,即;考虑i-2个物品乱序,第i-1个和第i个首先在原来的位置,两种方法使得乱序,一种和第i个交换(不能和前i-2个交换,那样成dp[i-1]),还有一种是第i个先和第i-1个交换,再和前i-2个其中一个交换,即,仔细想想,这个和dp[i-1]是不同的交换方法。

    另外:

      还有二维的dp写法,虽然高精度开不了,但是还是有启发意义。设dp[i][j]表示i个物品j个乱序的方案数,状态转移方程,最后一项的(i-j+1)的意思是从前i-1个中选择在原来位置的物品进行交换,即

    #include <bits/stdc++.h>
    
    const int MAXN = 2000 + 5;
    struct bign {
    	int len, num[MAXN];
    
    	bign () {
    		len = 0;
    		memset(num, 0, sizeof(num));
    	}
    	bign (int number) {*this = number;}
    	bign (const char* number) {*this = number;}
    
    	void DelZero ();
    	void Put ();
    
    	void operator = (int number);
    	void operator = (char* number);
    
    	bool operator <  (const bign& b) const;
    	bool operator >  (const bign& b) const { return b < *this; }
    	bool operator <= (const bign& b) const { return !(b < *this); }
    	bool operator >= (const bign& b) const { return !(*this < b); }
    	bool operator != (const bign& b) const { return b < *this || *this < b;}
    	bool operator == (const bign& b) const { return !(b != *this); }
    
    	void operator ++ ();
    	void operator -- ();
    	bign operator + (const int& b);
    	bign operator + (const bign& b);
    	bign operator - (const int& b);
    	bign operator - (const bign& b);
    	bign operator * (const int& b);
    	bign operator * (const bign& b);
    	bign operator / (const int& b);
    	//bign operator / (const bign& b);
    	int operator % (const int& b);
    };
    
    bign dp[805];
    
    int main() {
        dp[0] = 0; dp[1] = 0; dp[2] = 1;
        for (int i=3; i<=800; ++i) {
            dp[i] = (dp[i-1] + dp[i-2]) * (i - 1);
        }
        int n;
        while (scanf ("%d", &n) == 1 && n != -1) {
            dp[n].Put ();
            puts ("");
        }
        return 0;
    }
    
    void bign::DelZero () {
    	while (len && num[len-1] == 0)
    		len--;
    
    	if (len == 0) {
    		num[len++] = 0;
    	}
    }
    
    void bign::Put () {
    	for (int i = len-1; i >= 0; i--) 
    		printf("%d", num[i]);
    }
    
    void bign::operator = (char* number) {
    	len = strlen (number);
    	for (int i = 0; i < len; i++)
    		num[i] = number[len-i-1] - '0';
    
    	DelZero ();
    }
    
    void bign::operator = (int number) {
    
    	len = 0;
    	while (number) {
    		num[len++] = number%10;
    		number /= 10;
    	}
    
    	DelZero ();
    }
    
    bool bign::operator < (const bign& b) const {
    	if (len != b.len)
    		return len < b.len;
    	for (int i = len-1; i >= 0; i--)
    		if (num[i] != b.num[i])
    			return num[i] < b.num[i];
    	return false;
    }
    
    void bign::operator ++ () {
    	int s = 1;
    
    	for (int i = 0; i < len; i++) {
    		s = s + num[i];
    		num[i] = s % 10;
    		s /= 10;
    		if (!s) break;
    	}
    
    	while (s) {
    		num[len++] = s%10;
    		s /= 10;
    	}
    }
    
    void bign::operator -- () {
    	if (num[0] == 0 && len == 1) return;
    
    	int s = -1;
    	for (int i = 0; i < len; i++) {
    		s = s + num[i];
    		num[i] = (s + 10) % 10;
    		if (s >= 0) break;
    	}
    	DelZero ();
    }
    
    bign bign::operator + (const int& b) {
    	bign a = b;
    	return *this + a;
    }
    
    bign bign::operator + (const bign& b) {
    	int bignSum = 0;
    	bign ans;
    
    	for (int i = 0; i < len || i < b.len; i++) {
    		if (i < len) bignSum += num[i];
    		if (i < b.len) bignSum += b.num[i];
    
    		ans.num[ans.len++] = bignSum % 10;
    		bignSum /= 10;
    	}
    
    	while (bignSum) {
    		ans.num[ans.len++] = bignSum % 10;
    		bignSum /= 10;
    	}
    
    	return ans;
    }
    
    bign bign::operator - (const int& b) {
    	bign a = b;
    	return *this - a;
    }
    
    
    bign bign::operator - (const bign& b) {
    	int bignSub = 0;
    	bign ans;
    	for (int i = 0; i < len || i < b.len; i++) {
    		bignSub += num[i];
    		bignSub -= b.num[i];
    		ans.num[ans.len++] = (bignSub + 10) % 10;
    		if (bignSub < 0) bignSub = -1;
    	}
    	ans.DelZero ();
    	return ans;
    }
    
    bign bign::operator * (const int& b) {
    	int bignSum = 0;
    	bign ans;
    
    	ans.len = len;
    	for (int i = 0; i < len; i++) {
    		bignSum += num[i] * b;
    		ans.num[i] = bignSum % 10;
    		bignSum /= 10;
    	}
    
    	while (bignSum) {
    		ans.num[ans.len++] = bignSum % 10;
    		bignSum /= 10;
    	}
    
    	return ans;
    }
    
    bign bign::operator * (const bign& b) {
    	bign ans;
    	ans.len = 0; 
    
    	for (int i = 0; i < len; i++){  
    		int bignSum = 0;  
    
    		for (int j = 0; j < b.len; j++){  
    			bignSum += num[i] * b.num[j] + ans.num[i+j];  
    			ans.num[i+j] = bignSum % 10;  
    			bignSum /= 10;
    		}  
    		ans.len = i + b.len;  
    
    		while (bignSum){  
    			ans.num[ans.len++] = bignSum % 10;  
    			bignSum /= 10;
    		}  
    	}  
    	return ans;
    }
    
    bign bign::operator / (const int& b) {
    
    	bign ans;
    
    	int s = 0;
    	for (int i = len-1; i >= 0; i--) {
    		s = s * 10 + num[i];
    		ans.num[i] = s/b;
    		s %= b;
    	}
    
    	ans.len = len;
    	ans.DelZero ();
    	return ans;
    }
    
    int bign::operator % (const int& b) {
    
    	bign ans;
    
    	int s = 0;
    	for (int i = len-1; i >= 0; i--) {
    		s = s * 10 + num[i];
    		ans.num[i] = s/b;
    		s %= b;
    	}
    
    	return s;
    }
    

      

  • 相关阅读:
    最大子列和问题(20 分)浙大版《数据结构(第2版)》题目集
    习题2.1 简单计算器(20 分)浙大版《数据结构(第2版)》题目集
    习题2.2 数组循环左移(20 分)浙大版《数据结构(第2版)》题目集
    习题2.3 数列求和-加强版(20 分)浙大版《数据结构(第2版)》题目集
    java之不同数据流应用举例
    java之java.io.File的相关方法
    java之注解
    java之枚举和注解
    java之泛型
    java之操作集合的工具类--Collections
  • 原文地址:https://www.cnblogs.com/Running-Time/p/5658559.html
Copyright © 2020-2023  润新知