首页 > 技术文章 > [HDU5970] 最大公约数

DarthVictor 2020-05-30 11:56 原文

题目

原题地址

解说

我承认看了半天真不会只会暴力,看的题解,结果第一篇题解带的代码还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;
}

幸甚至哉,歌以咏志。

推荐阅读