hdu5970

真是怀疑当初合肥赛区怎么考这么差的……

首先根据辗转相除法可知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

hdu5970的相关文章

CCPC2016合肥现场赛

A(hdu5961):(BFS) 题意:给两个有向图=P=(V,E?P??)和Q=(V,E?Q??), 满足1.E?P??与E?Q??没有交:2.E?P??∪E?Q??是竞赛图.判断P与Q是否同时为传递的.一个有向图G是传递的,当且仅当对任意三个不同的顶点a,b,c,若有一条边从a到b且有一条边从b到c,则同样有一条边从a到c. 分析:首先的想法是从所有入度为0的点开始BFS,如果有某个点第一次被更新的时间>=2就肯定不行,然而就发现反例了,后来一想,从每个点开始BFS判断就行了 C(hdu59