[bzoj3142]数列

3142: [Hnoi2013]数列

Time Limit: 3 Sec Memory Limit: 128 MB
Submit: 1744 Solved: 866
[Submit][Status][Discuss]
Description

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

sol:

很有趣的一道题。
看着20%的数据以为是100%的数据,因为我一开始只会n^2的做法。
我们考虑把这个序列拿去差分,那么一个差分序列提供的贡献是
nia[i] n − ∑ i a [ i ]
那很多个差分序列的话就是
j(nia[i]) ∑ j ( n − ∑ i a [ i ] ) 枚举个j表示我们把a[i]数组给动了动,注意因为题目保证了m(k-1) < n所以这个式子完全成立的
提一提
nMk1jia[i] n ∗ M k − 1 − ∑ j ∑ i a [ i ]
容易发现固定了某个位置上的某个数,单独算这个数的贡献的话,他会提供
Mk2 M k − 2 次的贡献。能换位置的话就*(k-1).
既然每个数都这样,那就对数求个和,然后*后面的系数即可。

#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
typedef double db;
ll n,m,k;
ll pyz;
inline ll ksm(ll s,ll t)
{
    s%=pyz;
    int res=1;
    while(t)
    {
        if(t&1) res=(ll)res*s%pyz;
        s=(ll)s*s%pyz;
        t>>=1;
    }
    return res;
}
int main()
{
//  freopen("3142.in","r",stdin);
//  freopen(".out","w",stdout);
    cin>>n>>k>>m>>pyz;
    printf("%lld\n",(n%pyz*ksm(m,k-1)%pyz-m*(1+m)/2%pyz*ksm(m,k-2)%pyz*(k-1)%pyz+pyz)%pyz);
}

你可能感兴趣的:(bzoj)