hdu 5970 最大公约数

在这里插入图片描述
由于数据是随机的,所以每组数据都 O ( m 2 c ) O(m^2c) O(m2c)来跑就能过…

没有想到枚举c来做 …以后遇到这种推式子的多试试枚举几个

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 2e5 + 10;
#define fi first
#define se second
#define pb push_back
#define wzh(x) cerr<<#x<<'='<<x<<endl;
int mod;
int add(int x,int y){
  x+=y;
  if(x>=mod)x-=mod;
  if(x<0)x+=mod;
  return x;
}
int mul(int x,int y){
  return 1ll*x*y%mod;
}
int sub(int x,int y){
  x=x+mod-y;
  if(x>=mod)x-=mod;
  return x;
}
int ksm(int x,int y,int z=1){
  for(;y;y>>=1,x=mul(x,x))if(y&1)z=mul(z,x);
  return z;
}
int fac[N],inv[N];
void P(){
  fac[0]=1;
  for(int i=1;i<N;i++)fac[i]=mul(fac[i-1],i);
  inv[N-1]=ksm(fac[N-1],mod-2);
  for(int i=N-2;i>=0;i--)inv[i]=mul(inv[i+1],i+1);
}
int di(int x,int y){
  return mul(x,ksm(y,mod-2));
}
LL C(int x,int y){
  return mul(fac[x],mul(inv[y],inv[x-y]));
}
int f[667][667];
int gc[667][667];
void F(int x,int y){
  int c=0;
  int dx=x,dy=y;
  while(y>0){
    c++;
    int t=x%y;
    x=y;
    y=t;
  }
  f[dx][dy]=c;
  gc[dx][dy]=x;
  assert(c&&x);
}
mt19937 mt(time(0));
int t,n,m;
int main() {
  ios::sync_with_stdio(false);
  int pp=0;
  for(int i=1;i<=666;i++){
    for(int j=1;j<=666;j++){
      F(i,j);
      pp=max(pp,f[i][j]*gc[i][j]*gc[i][j]);
    }
  }
  for(cin>>t;t;t--){
    cin>>n>>m>>mod;LL ans=0;
    for(int i=1;i<=m&&i<=n;i++){
      for(int j=1;j<=i;j++){
        int C=f[j][i];
        int R=C*gc[j][i]*gc[j][i];
        for(int k=0;k<C&&k*i+j<=n;k++){
          int mx=(n-j-i*k)/(C*i);
          LL L=i*i/(gc[j][i]*gc[j][i]);
          L*=1ll*(1+mx)*mx/2 %mod;L%=mod;
          L+=1ll*i*(j+i*k)/R *(mx+1)%mod;
          L%=mod;
          ans=add(ans,L);
        }
      }
    }
    cout<<ans<<'\n';

  }
  return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值