「fj夏令营」求和
「题目描述」
作为本场考试最水的一题,给定 n,k 和 m,请你计算: (1^k +2^k +3^k +…+n^k) mod m
「输入格式」
从 sum.in 中输入数据 一行,三个整数,n,k,m
「输出格式」
输出到 sum.out 中
一行,(1k +2k +3k +…+nk) mod m
「样例输入」
4 3 98
「样例输出」
2
「数据规模与约定」
数据规模
1 :n≤2^63 −1,k=1,m≤2^31 −1
2-3:n ≤ 10^6,k ≤ 100,m ≤ 10^7
4-5:n ≤ 10^8,k ≤ 10^7,m ≤ 3 ∗ 10^7
6-10:n ≤ 2^63 −1,k ≤ 2^63 −1,m ≤ 1.5∗10^6
题解
本题时限为2s。。。事实上标程极限数据正好卡过。。。
k=1直接等差数列求和
因为a^k%m=(a%m)^k%m,所以只需要算出1-min(n,m)的答案
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
#include<iostream> #include<cstdio> #define ll long long using namespace std; ll n,k,m,l,ans; ll a[3000005],b[3000005]; int main() { //freopen("sum.in","r",stdin); //freopen("sum.out","w",stdout); scanf("%I64d%I64d%I64d",&n,&k,&m); if(k==1) { if(n&1)printf("%I64d",(n%m)*((n+1)/2%m)%m); else printf("%I64d",(n/2%m)*((n+1)%m)%m); return 0; } l=min(n,m); for(int i=1;i<=l;i++) b[i]=i%m,a[i]=1; while(k) { if(k&1) for(int i=1;i<=l;i++) a[i]=a[i]*b[i]%m; for(int i=1;i<=l;i++) b[i]=b[i]*b[i]%m; k>>=1; } ll t1=n/l%m,t2=n%l; for(int i=1;i<=l;i++) ans=(ans+a[i]%m)%m; ans=ans*t1%m; for(int i=1;i<=t2;i++) ans=(ans+a[i]%m)%m; printf("%I64d\n",ans); return 0; } |
Subscribe