问题描述如下:
问题不难,最大的问题是溢出,如果使用long long而直接暴力求借,溢出问题依旧存在。如何解决呢,不难得出第i个人心中的数是1+(1+2+3+……+(i-1)),所以到下一次栋栋心里的数为1+(1+2+3+4+5+……+n);其中n为已经有n人次报过数;
为了避免溢出,笔者的做法是保留上次栋栋报数的值,假设为num,统计栋栋本轮报数相对于上轮的增量,这个增量通过使用等差数列公式求出:即(left+right)*n/2;这里用到一个技巧,即先对left取余,而非计算出结果之后再取余,能有效避免溢出:
#include<iostream>
using namespace std;
long long getResult(long long nn,long long kk,long long TT){
long long result=1;
long long left=1,right=nn;
long long num=1;
for(int i=1;i<TT;i++){
num=num+((left+right)*nn/2)%kk;
//cout<<"L:"<<l<<" R: "<<r<<endl;
num%=kk;
//cout<<"num: "<<num<<endl;
result=result+num;
left=left+nn;
if(left>=kk){
left%=kk;
}
right=left+nn-1;
}
return result;
}
int main(){
long long n,k,T;
cin>>n>>k>>T;
cout<<getResult(n,k,T)<<endl;
}