zoukankan      html  css  js  c++  java
  • BZOJ3142 [Hnoi2013]数列

    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作。

     

    本文作者:ljh2000
    作者博客:http://www.cnblogs.com/ljh2000-jump/
    转载请注明出处,侵权必究,保留最终解释权!

     

    Description

    小 T最近在学着买股票,他得到内部消息:F公司的股票将会疯涨。股票每天的价格已知是正整数,并且由于客观上的原因,最多只能为N。在疯涨的K天中小T观察 到:除第一天外每天的股价都比前一天高,且高出的价格(即当天的股价与前一天的股价之差)不会超过M,M为正整数。并且这些参数满足M(K- 1)<N。
    小T忘记了这K天每天的具体股价了,他现在想知道这K天的股价有多少种可能

    Input

    只有一行用空格隔开的四个数:N、K、M、P。对P的说明参见后面“输出格式”中对P的解释。
    输入保证20%的数据M,N,K,P≤20000,保证100%的数据M,K,P≤109,N≤1018 。

    Output

    仅包含一个数,表示这K天的股价的可能种数对于P的模值。

    Sample Input

    7 3 2 997

    Sample Output

    16
    【样例解释】
    输出样例的16表示输入样例的股价有16种可能:
    {1,2,3},{1,2,4},{1,3,4},{1,3,5}, {2,3,4},{2,3,5},{2,4,5},{2,4,6}, {3,4,5},{3,4,6},{3,5,6},{3,5,7},{4,5,6},{4,5,7},{4,6,7},{5,6,7}

     

     

    正解:组合数学

    解题报告:

      这道题是一道很好的组合数学题,正好为我这种蒟蒻提供数学新思路...

      首先我们考虑如果我们按照枚举每天的股价这个思路的话,显然是行不通的,因为股价的确定除了枚举,并没有什么很好的思路。所以只能另辟蹊径。

      题目中说到了每天的增长状况,也就是在提醒我们这是一种很好的思路。考虑原数列我们用A表示,我们令ai=Ai+1-Ai,那么∑ai(1<=i<=k-1)=Ak-A1,然而A1是未知的,而且Ak<=n,那么我们可以发现A1的取值范围其实是可以得出来的,就是[1,n-∑ai]之间。那么我们考虑如果我们确定了一个a的数列,我们只能确定变化趋势,也就是说A1和a序列共同决定了这个序列的原本的样子,所以假如我们确定了a数列,可以得到的原数列有n-∑ai种。而a序列根据组合数学,一共有mk-1种可能性,所以我们可以发现整个序列一共有mk-1*(n-∑ai)种可能。

      然后我们可以发现n可以先提出来,变成mk-1*n-mk-1*∑ai,然后a序列怎么考虑呢,因为一共只可能有m种取值,所以把所有的可行的a序列(长度均为k-1)列举出来,有mk-1*(k-1)。因为每个取值的出现次数相等,所以每个数字出现了mk-2*(k-1)。然后根据等差数列提一下公因式可以得出来的。

      注意几个问题:取模的时候注意不要炸了中间值!有除法的一定要谨慎!

      具体代码如下:

     

     1 //It is made by jump~
     2 #include <iostream>
     3 #include <cstdlib>
     4 #include <cstring>
     5 #include <cstdio>
     6 #include <cmath>
     7 #include <algorithm>
     8 #include <ctime>
     9 #include <vector>
    10 #include <queue>
    11 #include <map>
    12 #include <set>
    13 using namespace std;
    14 typedef long long LL;
    15 const int inf = (1<<30);
    16 LL n,k,m,p,ans;
    17 
    18 inline LL getint()
    19 {
    20     LL w=0,q=0; char c=getchar();
    21     while((c<'0' || c>'9') && c!='-') c=getchar(); if(c=='-') q=1,c=getchar(); 
    22     while (c>='0' && c<='9') w=w*10+c-'0', c=getchar(); return q ? -w : w;
    23 }
    24 
    25 inline LL fastpow(LL a,LL b){
    26     if(b==1) return a;   LL x=1;
    27     while(b>0) {
    28     if(b&1) x*=a,x%=p;
    29     a*=a; a%=p;
    30     b>>=1;
    31     }
    32     return x;
    33 }
    34 
    35 inline void work(){
    36     n=getint();  k=getint(); m=getint(); p=getint(); n%=p; m%=p;
    37     LL nn=fastpow(m,k-1);
    38     ans=nn;  ans*=n; ans%=p; 
    39     nn=fastpow(m,k-2);
    40     nn*=(k-1); nn%=p; 
    41     nn*=((m+1)*m/2)%p; nn%=p;     
    42     ans-=nn; ans%=p; ans+=p; ans%=p;
    43     printf("%lld",ans);
    44 }
    45  
    46 int main()
    47 {
    48     work();
    49     return 0;
    50 }
  • 相关阅读:
    WCF 、Web API 、 WCF REST 和 Web Service 的区别
    BusyIndicator using MVVM 忙碌状态指示器的的实现
    复制文件夹的方法 .net
    SQL/LINQ/Lamda
    CSLA验证规则总结
    C++中GB2312字符串和UTF-8之间的转换
    如何用VC编写供PB调用的DLL
    【转】lucene4.3.0 配置与调试
    cygwin主要命令
    【转】eclipse中window->preference选项中没有tomcat的解决方法
  • 原文地址:https://www.cnblogs.com/ljh2000-jump/p/5907411.html
Copyright © 2011-2022 走看看