JOI2006模擬試験2 問題5@C++(25)

よくある数学の組合せ論の知識かと思って解いたらミスった。そりゃ、組合せ論的な規模の数って言ったら多倍長だもんなあ。

つーかSTLに多倍長ってないのかよ使えねー!Javaならあるのに!Pythonなんか標準で多倍長だし!

多倍長ライブラリのバグで何度も爆発(wrongを出す)した。orz

#include <cstdio>
#include <algorithm>
#include <vector>

using namespace std;

typedef unsigned long long ullong;
typedef unsigned int uint;

//minimalist mutable unsigned decimal big number;
class decimal_big
{
private:
	//100000 separated digits value;
	vector<uint> digits;
public:
	void div(uint target) {
		ullong ull_target=target;
		ullong carry=0;
		for(vector<uint>::reverse_iterator i=digits.rbegin();i!=digits.rend();++i) {
			ulong ull_current=*i;
			ull_current=ull_current+carry;
			*i=(uint)(ull_current/ull_target);
			carry=(ull_current%ull_target)*100000;
		}
		while(!digits.empty() && digits.back()==0) {
			digits.pop_back();
		}
	}
	void mul(uint target) {
		ullong ull_target=target;
		uint carry=0;
		for(vector<uint>::iterator i=digits.begin();i!=digits.end();++i) {
			ullong ull_current=*i;
			ull_current=ull_current*ull_target+carry;
			*i=(uint)(ull_current%100000);
			carry=(uint)(ull_current/100000);
		}
		if(carry>0) {
			digits.push_back(carry);
		}
		while(!digits.empty() && digits.back()==0) {
			digits.pop_back();
		}
	}
	void print() {
		while(!digits.empty() && digits.back()==0) {
			digits.pop_back();
		}
		if(digits.empty()) {
			printf("0");
			return;
		}
		for(vector<uint>::reverse_iterator i=digits.rbegin();i!=digits.rend();++i) {
			if(i==digits.rbegin()) {
				printf("%u",*i);
			} else {
				printf("%05u",*i);
			}
		}
	}
	void set_single(uint single_value) {
		digits.clear();
		digits.push_back(single_value);
	}
	decimal_big() {
		
	}
};

void long_combination(int all,int select,decimal_big& dst)
{
	if(select<0 || select>all) {
		dst.set_single(0);
		return;
	}
	dst.set_single(1);
	for(int i=0;i<select;i++) {
		dst.mul(all-i);
		dst.div(1+i);
	}
}

int main(int argc,char* argv[])
{
	int n,m,r;
	scanf("%d %d %d\n",&n,&m,&r);
	int realr=r-n*m;
	int separators=n-1;
	decimal_big pattern;
	long_combination(realr+separators,separators,pattern);
	pattern.print();
	printf("\n");
	return 0;
}