题目
题解
这道题 x 非常大,所以可以通过 x = sy + k, 用 y代换掉x 。
然后易证gcd(k,y) == gcd(x,y),而且这两个 gcd 计算出来的 c 也是一样的。
由于 s 的范围是[0,(x - k)/y], 所以当 x 特别大的时候,s 也特别大。s 也需要分块处理,另 s = j*c + i,i 的范围是[0, 1-c],所以可以按照 i 的不同取值进行分块。
代码如下
#include <algorithm>
#include <bitset>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <climits>
#include <iostream>
#include <list>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <vector>
using namespace std;
typedef long long ll;
int c;
int calc(int x, int y){
c = 0;
while(y>0){
c += 1;
int t = x%y;
x = y;
y = t;
}
return x;
}
int n,m,p;
int main(){
int T;
cin >> T;
while(T--){
cin>>n>>m>>p;
ll res = 0;
for(int y=1; y<=m; y++){
for(int k=0; k<y; k++){
ll gcd = calc(k,y);
ll ms = (n-k)/y;
ll a = k*y/gcd/gcd;
ll b = y*y/gcd/gcd;
ll tmp1, tmp2;
ll t = ms/c;
for(int i=0; i<c; i++) {
ll time = t*(t-1)/2;
tmp1 = (a+i*b)/c * t;
tmp2 = time*b;
res = (res + tmp1 + tmp2) % p;
}
ms = ms % c;
for(int i=0;i<=ms;++i) {
res = ((res + (a+i*b)/c) % p + b * t) % p;
}
}
}
cout<<res<<endl;
}
}