51nod 1149 Pi的递推式 组合数

题目大意:

(F(x) = 1 (0 leq x < 4))
(F(x) = F(x-1) + F(x-pi) (4 leq x))

给定(n),求(F(n))

题解:

我们把所有的数表示为(a - b*pi)
然后把所有的二元对((a,b))映射到坐标。
我们发现递归求解时经过的所有的边和映射出来的点构成了一张网格图。
所以我们直接应用组合数进行方案数计算即可.

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
typedef long long ll;
inline void read(int &x){
	x=0;char ch;bool flag = false;
	while(ch=getchar(),ch<'!');if(ch == '-') ch=getchar(),flag = true;
	while(x=10*x+ch-'0',ch=getchar(),ch>'!');if(flag) x=-x;
}
const int mod = 1e9+7;
const double pi = acos(-1);
int fac[1200010],inv[1200010];
inline int qpow(int x,int p){
	int ret = 1;
	for(;p;p>>=1,x=1LL*x*x % mod) if(p&1) ret=1LL*ret*x % mod;
	return ret;
}
inline void pre(){
	int n = 1000010;
	fac[0] = 1;
	for(int i=1;i<=n;++i) fac[i] = 1LL*i*fac[i-1] % mod;
	inv[n] = qpow(fac[n],mod-2);
	for(int i=n-1;i>=0;--i) inv[i] = 1LL*inv[i+1]*(i+1) % mod;
}
inline int C(int n,int m){
	if(n < m) return 0;
	return 1LL*fac[n]*inv[m]%mod*inv[n-m]%mod;
}
int main(){
	pre();
	int num;read(num);
	int n = 3,m = 0,ans = 0;
	if(num < 4) return puts("1");
	for(;n <= num;++n){
		if(n - m*pi >= 4){
			ans += C(num-n+m,m)*2 % mod;
			++ m;
		}else if(m > 0) ans += C(num-n+m-1,m-1);
		if(ans >= mod) ans -= mod;
	}
	printf("%d
",ans);
	return 0;
}
原文地址:https://www.cnblogs.com/Skyminer/p/6601977.html