【Luogu】P3228数列(数学题)

  题目链接

  考虑我们把所有的增加量拿出来做成一个序列b。

  那么在所有n中开头中$1~\sum\limits_{i=1}^{k-1}b[i]$是合法的

  也就是说我们枚举所有b[i],然后答案就是$n*m^{k-1}-\sum\sum b[i]$

  后面那个“对所有可能的序列b的序列和求和”怎么算呢?

  考虑到题目中神奇的限制m*(k-1)<n,也就是说b序列的任意一位1~m都是随便取的

  因此等差数列求1~m前缀和乘上每个数出现的次数即可。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cctype>
#include<cstdlib>
using namespace std;
inline long long read(){
    long long num=0,f=1;
    char ch=getchar();
    while(!isdigit(ch)){
        if(ch=='-')    f=-1;
        ch=getchar();
    }
    while(isdigit(ch)){
        num=num*10+ch-'0';
        ch=getchar();
    }
    return num*f;
}

long long n,m,e,mod;

long long Pow(long long a,long long b){
    long long ret=1;
    while(b){
        if(b&1)    ret=ret*a%mod;
        a=a*a%mod;
        b>>=1;
    }
    return ret;
}

int main(){
    n=read(),e=read(),m=read(),mod=read();
    long long ans=(n%mod)*Pow(m,e-1)%mod;
    long long now=(1+m)*m/2%mod*(e-1)%mod*Pow(m,e-2);
    printf("%lld\n",((ans-now)%mod+mod)%mod);
    return 0;
}

 

posted @ 2018-05-03 09:48 Konoset 阅读(...) 评论(...) 编辑 收藏