题目大意
F(x) = 1 (0 <= x < 4)
F(n) = F(n - 1) + F(n - pi) (4 <= x)
Pi = 3.1415926535…..
现在给出一个N,求F(n)。由于结果巨大,只输出Mod 10^9 + 7的结果即可。
n≤1000000
分析
一个很好的思路。
这样的递推过程可以看成一个DAG,求编号为n的点到编号为{x,∈[0,4)}的点到的路径总数。
首先对最后一步分类讨论:-1或是-Pi,然后再枚举-Pi的次数,把组合数加起来。
时间复杂度O(n)
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
const int maxn=1e6+5,mo=1e9+7;
const double pi=acos(-1);
typedef long long LL;
int n,Fac[maxn],Inv[maxn],inv[maxn],ans;
int C(int n,int m)
{
return (LL)Fac[n]*Inv[m]%mo*Inv[n-m]%mo;
}
int main()
{
scanf("%d",&n);
if (n<4)
{
printf("1\n"); return 0;
}
Fac[0]=Inv[0]=Fac[1]=Inv[1]=inv[1]=1;
for (int i=2;i<=n;i++)
{
Fac[i]=(LL)Fac[i-1]*i%mo;
inv[i]=(LL)inv[mo%i]*(mo-mo/i)%mo;
Inv[i]=(LL)Inv[i-1]*inv[i]%mo;
}
for (int i=0;n-i*pi>=4;i++)
{
int j=n-i*pi-3;
ans=(ans+C(i+j-1,i))%mo;
}
for (int i=0;n-i>=4;i++)
{
int j=(double)(n-i-4)/pi;
ans=(ans+C(i+j,i))%mo;
}
printf("%d\n",ans);
return 0;
}