[HDU5970] 最大公约数
题目
解说
我承认看了半天真不会只会暴力,看的题解,结果第一篇题解带的代码还T了还得再看一篇。
直接参阅此博客,讲解比较详细但是提供的代码是\(T\)的。
代码可以参阅此博客。
代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 700;
int gcd[maxn][maxn],num[maxn][maxn];
int n,m,p;
ll calc(ll x,ll y,ll tot,ll cnt){
ll ans = (tot+1)*(x*y)+(tot+1)*tot/2*(y*y);
ll rd = y*y%cnt;
ll ra = y*x%cnt;
ll res = 0;
for(int i=0;i<cnt;++i){
res += (rd*i+ra)%cnt;
}
res = tot/cnt*res;
for(int i=0;i<=tot%cnt;++i){
res += (rd*i+ra)%cnt;
}
return (ans-res)/cnt%p;
}
void init()
{
for(int i=0;i<maxn;i++)
for(int j=0;j<maxn;j++)
if(i==0||j==0) gcd[i][j]=i+j;
else if(i<j) gcd[i][j] = gcd[i][j%i];
else gcd[i][j] = gcd[i%j][j];
for(int i=1;i<maxn;i++)
for(int j=0;j<i;j++){
if(j==0) num[i][j] = 1;
else num[i][j] = num[j][i%j] +1;
}
}
int main(){
init();
int T;
scanf("%d",&T);
while(T--){
int ans = 0;
scanf("%d%d%d",&n,&m,&p);
for(int i=1;i<=m;i++)
for(int j=0;j<i&&j<=n;j++){
ans+=calc(j/gcd[i][j],i/gcd[i][j],(n-j)/i,num[i][j]);
ans%=p;
}
printf("%d\n",ans);
}
return 0;
}
幸甚至哉,歌以咏志。
签名:
我将轻轻叹息,叙述这一切,
许多许多年以后:
林子里有两条路,我——
选择了行人稀少的那一条,
它改变了我的一生。