真是怀疑当初合肥赛区怎么考这么差的……
首先根据辗转相除法可知f(i,j)=f(i+j*k,j)
于是我们可以先于处理出f(i,j) (j<=666,i<=j),当确定i,j时c也确定
(x=gcd(i,j))可见,当确定了i,j,k后,后面p的求和就是一个等差数列的求和
c是logm级的所以总复杂度就是O(T*m^2*logm)
1 #include<bits/stdc++.h> 2 3 using namespace std; 4 typedef long long ll; 5 int f[670][670],c[670][670],n,m,p; 6 int get(int x,int y,int &f,int &c) 7 { 8 int t; c=0; 9 while (y) 10 { 11 c++; 12 t=x%y; x=y; y=t; 13 } 14 f=c*x*x; 15 } 16 17 int main() 18 { 19 int cas; 20 scanf("%d",&cas); 21 for (int j=1; j<=666; j++) 22 for (int i=1; i<=j; i++) 23 get(i,j,f[i][j],c[i][j]); 24 while (cas--) 25 { 26 scanf("%d%d%d",&n,&m,&p); 27 ll ans=0; 28 for (int j=1; j<=m; j++) 29 for (int i=1; i<=j&&i<=n; i++) 30 for (int k=0; k<c[i][j]; k++) 31 { 32 if (i+k*j>n) break; 33 ll b=(i+j*k)*j/f[i][j]; 34 ll d=c[i][j]*j*j/f[i][j]; 35 ll t=(n-(i+j*k))/(c[i][j]*j)+1; 36 ans=(ans+b*t%p+(t-1)*t/2%p*d%p)%p; 37 } 38 printf("%lld\n",ans); 39 } 40 }
时间: 2024-10-10 23:35:46