51NOD 1149:Pi的递推式——题解

http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1149

F(x) = 1 (0 <= x < 4)
F(x) = F(x - 1) + F(x - pi) (4 <= x)
Pi = 3.1415926535.....
现在给出一个N,求F(N)。由于结果巨大,只输出Mod 10^9 + 7的结果即可。

不好想啊……以及我曾经打了个表,并且还找到了规律,结果过到29就gg了……

参考:https://blog.csdn.net/qq_36797743/article/details/78930126

为了方便理解,我们可以把题意变成:有个数,初值为0,每次可以$+1/+pi$,求有多少种方法使得该数$(x-4,x]$。

那就……也不好办啊。如果我们设达到目标状态需要+1次数为$s$,+pi次数为$t$,那么显然答案贡献为$C(s+t,t)$。

只是s和t的值不好求。其实,我们可以划一个界限值i,这样$s=x-i$,t就表示到达$(i-4,i]$所需要的+pi次数了。

$P[i]=(i-4)/pi+1$就求出来了。

但是我们求的是到达$(x-4,x]$即停止,有时我们不需要那么多pi,所以需要减掉。

#include<map>
#include<cmath>
#include<stack>
#include<queue>
#include<cstdio>
#include<cctype>
#include<vector>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef double dl;
typedef long long ll;
const dl pi=acos(-1.0);
const int p=1e9+7;
const int N=1e6+5;
inline int qpow(int k,int n){
    int res=1;
    while(n){
        if(n&1)res=(ll)res*k%p;
        k=(ll)k*k%p;n>>=1;
    }
    return res;
}
int jc[N],inv[N],P[N];
void init(int n){
    jc[0]=1;
    for(int i=1;i<=n;i++)jc[i]=(ll)jc[i-1]*i%p;
    inv[n]=qpow(jc[n],p-2);
    for(int i=n-1;i;i--)inv[i]=(ll)inv[i+1]*(i+1)%p;
    inv[0]=1;
}
inline int C(int n,int m){
    return (ll)jc[n]*inv[m]%p*inv[n-m]%p;
}
int solve(int n){
    if(n<4)return 1;
    for(int i=4;i<=n;i++)P[i]=(dl)(i-4)/pi+1;
    int ans=0;
    for(int i=n;i>=3;i--){
        int s=n-i,t=P[i]-(P[i+1]<=P[i]);
        (ans+=C(s+t,s))%=p;
    }
    return ans;
}
int main(){
    int n;
    scanf("%d",&n);
    init(n);
    printf("%d\n",solve(n));
    return 0;
}

+++++++++++++++++++++++++++++++++++++++++++

 +本文作者:luyouqi233。               +

 +欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/+

+++++++++++++++++++++++++++++++++++++++++++

猜你喜欢

转载自www.cnblogs.com/luyouqi233/p/9200909.html
今日推荐