P4345 [SHOI2015]超能粒子炮·改

白嫖怪

其中预处理组合数的方法是用的杨辉三角(c[i][j] = c[i-1][j] + c[i-1][j-1]),初始化为(c[0][0] = 1, c[i][0] = c[i][i] = 1 (1leq ileq maxn))

预处理f的转移方程为(f[i][j] = f[i][j-1] + c[i][j]),初始化为(f[i][0] = 1(0 leq i leq maxn))

放一下代码qwq:

#include <bits/stdc++.h>
using namespace std;

template<typename temp>temp read(temp &x){
	x = 0;temp f = 1;char ch;
	while(!isdigit(ch = getchar())) (ch == '-') and (f = -1);
	for(x = ch^48; isdigit(ch = getchar()); x = (x<<1)+(x<<3)+(ch^48));
	return(x *= f);
}
template <typename temp, typename ...Args>void read(temp& a, Args& ...args){read(a), read(args...);}

const int maxn = 2333, p = 2333;

#define ll long long

int t;
ll c[maxn+100][maxn+100], f[maxn+100][maxn+100];

ll lucas(ll n, ll m){
	if(!m or n == m) return 1;
	if(n < m) return 0;
	return c[n%p][m%p]*lucas(n/p,m/p)%p;
}

ll answer(ll n, ll k){
	if(k < 0) return 0;
	if(!n or !k) return 1;
	if(n < p and k < p) return f[n][k];
	return (answer(n/p,k/p-1)*f[n%p][p-1]%p+lucas(n/p,k/p)*f[n%p][k%p])%p;
}

signed main(){
	read(t);
	c[0][0] = 1;
	for(int i = 1; i <= 2343; i ++){
		c[i][0] = c[i][i] = 1;
		for(int j = 1; j < i; j ++){
			c[i][j] = (c[i-1][j] + c[i-1][j-1])%p;
		}
	}
	for(int i = 0; i <= 2343; i ++) f[i][0] = 1;
	for(int i = 0; i <= 2343; i ++){
		for(int j = 1; j <= 2343; j ++){
			f[i][j] = (f[i][j-1] + c[i][j])%p;
		}
	}
	for(ll n, k; t; t --){
		read(n, k);
		printf("%lld
", answer(n,k));
	}
	return 0;
}
原文地址:https://www.cnblogs.com/Vanyun/p/13448918.html