[校内赛3-2][题解]matrix

原题洛谷P2158

本题出来就是防止你们AK的

首先,大家应该很容易发现这是原题(我都讲过),然后准备好了线性筛欧拉函数的模板

然后仔细一看:不对!n,m不相等,不能套板子!

只好乖乖枚举了,这样最好是O(nlogn),可以得60分(可以参照洛谷题解)

那么正解是什么呢?相信参照题解的同学们(如果有)一定看到了一个奇奇怪怪的算法:莫比乌斯反演!

今天我们要讲的就是这个

-莫比乌斯函数

-莫比乌斯反演

-整除分块优化

推荐blog:莫比乌斯反演基础,关于gcd的反演

这里模数也是个坑,很容易写顺手

std:

 1 #include
 2 #include
 3 #include
 4 #include
 5 #include
 6 #include
 7 #include
 8 #include
 9 #include
10 #include
11 #include
12 #include<set>
13 #include
14 #define LL long long
15 #define rg register
16 #define us unsigned
17 #define eps 1e-6
18 #define INF 0x3f3f3f3f
19 #define ls k<<1
20 #define rs k<<1|1
21 #define tmid ((tr[k].l+tr[k].r)>>1)
22 #define nmid ((l+r)>>1)
23 #define Thispoint tr[k].l==tr[k].r
24 #define pushup tr[k].wei=tr[ls].wei+tr[rs].wei
25 #define pub push_back
26 #define lth length
27 using namespace std;
28 inline void Read(LL &x){
29     LL f=1;
30     char c=getchar();
31     x=0;
32     while(c<'0'||c>'9'){
33         if(c=='-')f=-1;
34         c=getchar();
35     }
36     while(c>='0'&&c<='9'){
37         x=(x<<3)+(x<<1)+c-'0';
38         c=getchar();
39     }
40     x*=f;
41 }
42 #define N 10000010
43 #define mod 19268017
44 LL n,m,ans,Mu[N],Pri[N],Isntpri[N];
45 inline void Prime(LL n){//线性筛莫比乌斯函数 
46     Mu[1]=1;
47     for(rg LL i=2;i<=n;i++){
48         if(!Isntpri[i])Pri[++Pri[0]]=i,Mu[i]=-1;
49         for(rg LL j=1;j<=Pri[0]&&i*Pri[j]<=n;j++){
50             Isntpri[i*Pri[j]]=1;
51             if(i%Pri[j]==0)break;
52             Mu[i*Pri[j]]=-Mu[i];
53 //            这句话其实是Mu[i*Pri[j]]=Mu[i]*Mu[Pri[j]] 
54         }
55     }
56 }
57 int main(){
58     freopen("matrix.in","r",stdin);
59     freopen("matrix.out","w",stdout);
60     Read(n),Read(m);
61     n--,m--;
62     if(!n||!m){//特判 
63         if(!n&&!m)cout<<0<<endl;
64         else cout<<1<<endl;
65         return 0;
66     }
67     Prime(max(n,m));
68     for(rg LL i=1;i<=max(n,m);i++)Mu[i]=(Mu[i]+Mu[i-1])%mod;
69     for(rg LL Left=1,Right;Left<=max(n,m);Left=Right+1){
70         Right=max(n,m)/(max(n,m)/Left);//整除分块,直接跳到下一个商 
71         ans+=(Mu[Right]-Mu[Left-1])*(n/Left)%mod*(m/Left)%mod;
72     }
73     printf("%lld\n",((ans+2)%mod+mod)%mod);//加上一开始遗漏的两个 
74     return 0;
75 }
My Beautiful Code

 

你可能感兴趣的:([校内赛3-2][题解]matrix)