2693: jzptab - BZOJ

Description

 

Input

一个正整数T表示数据组数
接下来T行 每行两个正整数 表示N、M
Output

T行 每行一个整数 表示第i组数据的结果
Sample Input

1

 

4 5

 

Sample Output

122

 

HINT

T <= 10000

 

N, M<=10000000

 

 

题解君:http://hi.baidu.com/mikeni2006/item/b4f78a4520de9bab61d7b985

看了一上午才看懂,最后终于在lazycal的帮助下想出来了

我们需要先预处理出那个奇怪的前缀和就是

      d                                                                                                                                                                                                       Σ    d*  Σ    d'*μ(d')                                                                                                                                                                            i=1      d'|d

然后因为trunc(n/i)和trunc(m/i)都只有根号级别个值,也就是只要枚举这些值就行了

为了跑得快,类型用的longint,然后写了很多int64函数

 1 const
 2     maxn=10000010;
 3     h=100000009;
 4 var
 5     flag:array[0..maxn]of boolean;
 6     f,s:array[0..maxn]of longint;
 7     p:array[0..1000000]of longint;
 8     t,n,m,tot:longint;
 9   
10 function max(x,y:longint):longint;
11 begin
12     if x>y then exit(x);
13     exit(y);
14 end;
15   
16 function min(x,y:longint):longint;
17 begin
18     if x<y then exit(x);
19     exit(y);
20 end;
21   
22 function get(a:longint):longint;
23 begin
24     exit(((int64(a)*a+a)>>1)mod h);
25 end;
26   
27 procedure pre;
28 var
29     i,j:longint;
30 begin
31     f[1]:=1;
32     for i:=2 to 10000000 do
33       begin
34         if flag[i]=false then
35           begin
36             inc(tot);
37             p[tot]:=i;
38             f[i]:=1-i+h;
39           end;
40         for j:=1 to tot do
41           begin
42             if int64(p[j])*i>10000000 then break;
43             flag[p[j]*i]:=true;
44             if i mod p[j]=0 then
45               begin
46                 f[p[j]*i]:=f[i];
47                 break;
48               end
49             else f[p[j]*i]:=int64(f[i])*f[p[j]]mod h;
50           end;
51       end;
52     for i:=1 to 10000000 do
53       s[i]:=(int64(s[i-1])+int64(f[i])*i)mod h;
54 end;
55   
56 procedure main;
57 var
58     i,j,t,li,ri,lj,rj,l,r,ans:longint;
59 begin
60     read(n,m);
61     if n>m then
62     begin
63       t:=n;n:=m;m:=t;
64     end;
65     ans:=0;
66     i:=1;
67     while sqr(i)<=n do
68       begin
69         ans:=(int64(ans)+((int64(f[i])*i mod h)*get(trunc(n/i))mod h)*get(trunc(m/i)))mod h;
70         inc(i);
71       end;
72     j:=trunc(m/i);
73     i:=trunc(n/i);
74     while (i>0) and (j>0) do
75       begin
76         ri:=trunc(n/i);
77         li:=trunc(n/(i+1))+1;
78         lj:=trunc(m/(j+1))+1;
79         rj:=trunc(m/j);
80         l:=max(li,lj);
81         r:=min(ri,rj);
82         if l<=r then ans:=(int64(ans)+(int64(s[r]-s[l-1]+h)*get(i)mod h)*get(j))mod h;
83         if ri<=rj then dec(i)
84         else dec(j);
85       end;
86     writeln(ans);
87 end;
88   
89 begin
90     pre;
91     read(t);
92     while t>0 do
93       begin
94         dec(t);
95         main;
96       end;
97 end.
View Code

 

posted @ 2014-05-27 19:09  Randolph87  阅读(316)  评论(0编辑  收藏  举报