您的位置:首页 > 其它

【HNOI2013】数列

2015-12-13 18:41 176 查看

题目

小T最近在学着买股票,他得到内部消息:F公司的股票将会疯涨。

股票每天的价格已知是正整数,并且由于客观上的原因,最多只能为N。在疯涨的K天中小T观察到:除第一天外每天的股价都比前一天高,且高出的价格(即当天的股价与前一天的股价之差)不会超过M,M为正整数。并且这些参数满足M(K-1)

分析

我们发现若是从他们的各自股价开始入手,问题会变得很困难,

为什么呢?因为股价本身就是一个递增的值,不方便我们讨论方案数

于是我们可以从有限定的m入手,即每两天之间股价的差:

a[1],a[2],a[3],a[4]..a[k-1]

那么这样就不用去管每个a[i]的值之间的关系了。

若是确定了这k-1个数,那么很明显会有n−∑a[i]n-\sum a[i]的方案(即第一天的股价的值)

那么总的方案就是∑n−∑a[i]\sum n-\sum a[i]

然而这样想上面的数列一共有mk−1m^{k-1},我们先提取n出来,就是n∗mk−1n*m^{k-1}

而a[i]我们可以这样处理,因为一共有mk−1m^{k-1}个数列,也就是有mk−1∗(k−1)m^{k-1}*(k-1)个数

而且每一个数的范围都是1..m,出现的次数都是一样的也就是mk−1∗(k−1)/m=mk−2∗(k−1)m^{k-1}*(k-1)/m=m^{k-2}*(k-1)

这样的话,用等差数列求和,每m个数配一组总的就是mk−2∗(k−1)∗(m+1)∗m/2m^{k-2}*(k-1)*(m+1)*m/2

所以答案就是n∗mk−1−mk−2∗(k−1)∗(m+1)∗m/2n*m^{k-1}-m^{k-2}*(k-1)*(m+1)*m/2

到此便很好的解决问题了。这题关键是转换成差来思考。

[code]#include<iostream> 
#include<algorithm>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<cstdio>
using namespace std;
long long ans,n,m,k,p;
long long power(long long x,long long y,long long z){
    if (y==1) return x;
    else {
        long long e=power(x,y>>1,z);
        e=(e*e)%p;
        if (y%2==1) e=(e*x)%p;
        return e;
    }
}
int main(){
    scanf("%lld%d%d%d",&n,&k,&m,&p);
    n=n%p;
    ans=(power(m % p,k-1,p)*(n%p))%p;
    ans-=((power(m % p,k-2,p)*(k-1)% p)*(((m+1)*m/2)% p))%p;
    ans=(ans+p)%p;
    printf("%d",ans);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: