【BZOJ 2693】jzptab(莫比乌斯+分块)

2693: jzptab

Description

Input

一个正整数T表示数据组数

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

Output

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

Sample Input

1

4 5

Sample Output

122

HINT
T <= 10000

N, M<=10000000
 
 
【分析】
  bzoj2154的进化版!多组。。
  根据bzoj2154的推导我们有:
  
 对于这个把它放入线性筛里面预处理就好了。
 
 
  首先证明f[n]=∑i*mu[i](i|n)为积性函数:
  设函数g[n]=n*mu[n],那么f=1*g,1和g都是积性函数,所以f也是积性函数。
 
  线性筛的时候,当i%prime[j]!=0 由积性函数得,f[i*prime[j]]=f[i]*f[prime[j]]
  当i%prime[j]==0时,若再加入prime[j],mu值为0,所以对答案没有影响。即f[i*prime[j]]=f[i]。
  想这里的时候还是有思维局限,要记住当有一个质因子质数大于1时,mu值就为0了,这个特点前面一题也用到过!!
 
  还有一个不是很懂的地方就是为什么每次加进去时都要MOD成正数,表示不知道化简之后为什么不能加一个负数进去~~导致WA很久~~
 
代码如下:
 1 #include<cstdio>
 2 #include<cstdlib>
 3 #include<cstring>
 4 #include<iostream>
 5 #include<algorithm>
 6 #include<queue>
 7 #include<cmath>
 8 using namespace std;
 9 #define Mod 100000009
10 #define Maxn 10000010
11 #define LL long long
12 
13 LL mu[Maxn],pri[Maxn],g[Maxn],h[Maxn],pl;
14 bool q[Maxn];
15 
16 LL mymin(LL x,LL y) {return x<y?x:y;}
17 
18 void get_mu(LL mx)
19 {
20     pl=0;
21     memset(q,1,sizeof(q));
22     mu[1]=1;g[1]=1;
23     for(LL i=2;i<=mx;i++)
24     {
25         if(q[i])
26         {
27             pri[++pl]=i;
28             mu[i]=-1;
29             g[i]=1+i*mu[i];
30         }
31         for(LL j=1;j<=pl;j++)
32         {
33             if(i*pri[j]>mx) break;
34             q[i*pri[j]]=0;
35             if(i%pri[j]==0) mu[i*pri[j]]=0,g[i*pri[j]]=g[i];
36             else mu[i*pri[j]]=-mu[i],g[i*pri[j]]=(g[i]*g[pri[j]])%Mod;
37             if(i%pri[j]==0) break;
38         }
39     }
40     for(LL i=1;i<=mx;i++) g[i]=(i*g[i])%Mod;
41     h[1]=g[1];
42     for(LL i=2;i<=mx;i++) h[i]=(h[i-1]+g[i])%Mod;
43 }
44 
45 LL get_sum(LL x,LL y)
46 {
47     return ( ( ((x+1)*x/2)%Mod )*( ((y+1)*y/2)%Mod ) )%Mod;
48 }
49 
50 LL get_ans(LL n,LL m)
51 {
52     LL ans=0;
53     
54     LL sq=(LL)ceil(sqrt((double)m));
55     for(LL i=1;i<=mymin(sq,n);i++)
56     {
57         ans=(ans+(g[i]%Mod+Mod)%Mod*get_sum(n/i,m/i) )%Mod;
58     }
59     
60     
61     for(LL i=sq+1;i<=n;) 
62     {
63         LL x=n/i,y=m/i;
64         LL r1=n/x+1,r2=m/y+1;
65         LL r=mymin(r1,r2);
66         if(r>m+1) r=m+1;
67         // if((((h[r-1]-h[i-1])%Mod+Mod)%Mod)<0) while(1);
68         ans=( ans+(((h[r-1]-h[i-1])%Mod+Mod)%Mod)*get_sum(x,y) )%Mod;
69         i=r;
70     }
71     return ans;
72 }
73 
74 int main()
75 {
76     int T;
77     T=1;
78     scanf("%d",&T);
79     get_mu(10000000);
80     
81     while(T--)
82     {
83         LL n,m,t;
84         scanf("%lld%lld",&n,&m);
85         if(n>m) t=n,n=m,m=t;
86         
87         LL ans=get_ans(n,m);
88         
89         printf("%lld\n",ans);
90     }
91     return 0;
92 }
[BZOJ 2693]
 
 
2016-08-30 16:49:26
 
 
 
 
posted @ 2016-08-30 16:28  konjak魔芋  阅读(137)  评论(0编辑  收藏  举报