zoukankan      html  css  js  c++  java
  • 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://www.cnblogs.com/ivorysi/p/9197222.html

    (这个参考是个神,我这样的凡人能解读到这种地步已经很不容易了)

    总觉得我讲的很有问题啊……那我就顺着这个参考讲吧……

    将递归展开,你就会发现是一张图,而所求即为最上层点到最下层点的方案路径数。

    设$P[i]$表示到$i$这个点减几次pi到达其中一个终点,于是我们到达一次终点所需要经过的整数结点(即-1)与"非整数"结点(即-pi),可以通过设前者为$n-i$,则后者为$P[i]$,路径条数就可以用组合数求出。

    但是要注意的是我们只要到达其中一个目标即会停止,即5-1-pi是合法的,而5-pi-1则是不可能的,即有些pi只能放在最后减,我们需要把这些pi扣除。

    其实并不存在“这些”,事实上显然我们只有一个pi,也就是说下面的关键是判断这个pi是否会导致我们提前结束。

    我们考虑,只要$i$的父亲结点(其实是$i+1$,但叫做父亲节点更好懂些)$P[i+1]>P[i]$,那么我们随便了,提前拐或者不拐最终到达的状态一定一致。

    但是如果不满足的话,则我们在$i+1$或更早处转弯的话,就一定会导致我们提早结束,所以此时我们扣除这个pi即可。

    这是这个参考的做法,个人感觉并不如:https://blog.csdn.net/qq_36797743/article/details/78930126这个更好想一些,但是解法比较自然,顺畅。

    #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
    ",solve(n));
        return 0;
    }

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

     +本文作者:luyouqi233。               +

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

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

  • 相关阅读:
    CSS盒子模型
    getContextPath、getServletPath、getRequestURI、request.getRealPath的区别
    MYSQL中的CASE WHEN END AS
    单点登录的精华总结
    git&github
    June 21st 2017 Week 25th Wednesday
    June 20th 2017 Week 25th Tuesday
    June 19th 2017 Week 25th Monday
    June 18th 2017 Week 25th Sunday
    June 17th 2017 Week 24th Saturday
  • 原文地址:https://www.cnblogs.com/luyouqi233/p/9200909.html
Copyright © 2011-2022 走看看