[NOI2010][bzoj2005] 能量采集 [欧拉函数+分块前缀和优化]

题面:

传送门

思路:

稍微转化一下,可以发现,每个植物到原点连线上植物的数量,等于gcd(x,y)-1,其中xy是植物的横纵坐标

那么我们实际上就是要求2*sigma(gcd(x,y))-n*m了

又有某不知名神奇定理:一个数的所有因子的phi之和等于这个数本身,其中phi是欧拉函数

因此题目转化为求如下:

我们把式子变个型,就成了如下式子:

然后一个前缀和优化,O(n+sqrt(n))解决

Code:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 #define ll long long
 6 using namespace std;
 7 inline ll read(){
 8     ll re=0,flag=1;char ch=getchar();
 9     while(ch>‘9‘||ch<‘0‘){
10         if(ch==‘-‘) flag=-1;
11         ch=getchar();
12     }
13     while(ch>=‘0‘&&ch<=‘9‘) re=(re<<1)+(re<<3)+ch-‘0‘,ch=getchar();
14     return re*flag;
15 }
16 ll phi[100010],pri[100010],cnt,pre[100010];
17 void init(){
18     phi[1]=pre[1]=1;ll i,j,k;
19     for(i=2;i<=100010;i++){
20         if(!phi[i]) phi[i]=i-1,pri[++cnt]=i;
21         for(j=1;(j<=cnt)&&(i*pri[j]<=100010);j++){
22             if(i%pri[j]) phi[i*pri[j]]=phi[i]*(pri[j]-1);
23             else{phi[i*pri[j]]=phi[i]*pri[j];break;}
24         }
25         pre[i]=pre[i-1]+phi[i];
26 //        if(i<=10) cout<<"phi "<<i<<" "<<phi[i]<<"\n";
27     }
28 }
29 ll n,m;ll ans;
30 int main(){
31     init();ll i,j;
32     n=read();m=read();
33     if(n>m) swap(n,m);
34     for(i=1;i<=n;i=j+1){
35         j=min(n/(n/i),m/(m/i));
36         ans+=(ll)(n/i)*(m/i)*(pre[j]-pre[i-1]);
37     }
38     printf("%lld\n",ans*2-n*m);
39 }

∑ni=1∑mi=1∑d|m?d|ndphi(d)

∑ni=1∑mi=1∑d|m?d|ndphi(d)

原文地址:https://www.cnblogs.com/dedicatus545/p/8490836.html

时间: 2024-08-18 13:53:31

[NOI2010][bzoj2005] 能量采集 [欧拉函数+分块前缀和优化]的相关文章

【BZOJ2005】[Noi2010]能量采集 欧拉函数

[BZOJ2005][Noi2010]能量采集 Description 栋栋有一块长方形的地,他在地上种了一种能量植物,这种植物可以采集太阳光的能量.在这些植物采集能量后,栋栋再使用一个能量汇集机器把这些植物采集到的能量汇集到一起. 栋栋的植物种得非常整齐,一共有n列,每列有m棵,植物的横竖间距都一样,因此对于每一棵植物,栋栋可以用一个坐标(x, y)来表示,其中x的范围是1至n,表示是在第x列,y的范围是1至m,表示是在第x列的第y棵. 由于能量汇集机器较大,不便移动,栋栋将它放在了一个角上,

欧拉函数前缀和

今天软院校赛,有一道H题非常的神,所以记下来.题意转化了之后就是求欧拉函数的前缀和.自然的想法是O(n)的线性预处理可以求出前n个数的欧拉函数,又或者是O(sqrt(n))的预处理求出单个数的欧拉函数.但是题目要求的是前n(n<=10^9)个数欧拉函数的前缀和.于是我就觉得这是没法做的了,赛后问了出题人,出题人非常好的给了下面的这个链接. http://wzimpha.sinaapp.com/archives/596 然后大体的思路就在里面,这里也不重复了.主要是觉得这种方法好神,所以特别的在这

bzoj 1408 [Noi2002]Robot(欧拉函数)

[题目链接]  http://www.lydsy.com/JudgeOnline/problem.php?id=1408 [题意] 求m的所有约数中,满足可以分解成(奇数个不同素数/偶数个不同素数/其他)的所有的phi之和. [思路] ans1表示目前为止有偶数个奇质因子的欧拉函数的前缀和 ans2表示目前为止有奇数个奇质因子的欧拉函数的前缀和. 注意2不是奇质因子,需要去掉. 第三种可以由m-1减去前两种,减1为去掉1,1不是老师. [代码] 1 #include<cstdio> 2 #in

HDU5780 gcd (BestCoder Round #85 E) 欧拉函数预处理——分块优化

分析(官方题解): 一点感想: 首先上面那个等式成立,然后就是求枚举gcd算贡献就好了,枚举gcd当时赛场上写了一发O(nlogn)的反演,写完过了样例,想交发现结束了 吐槽自己手速慢,但是发了题解后发现,这题连O(n)欧拉函数前缀和的都卡了,幸亏没交,还是太年轻 对于官方题解说sqrt(n)优化(其实就是n/(小于n一段数)结果是一样的,也不算什么分块),还是很简单的,做反演题的时候看到过很多,只是忘记了 如果不会请看这篇解题报告http://wenku.baidu.com/view/fbe2

【bzoj4804】欧拉心算 欧拉函数

题目描述 给出一个数字N 输入 第一行为一个正整数T,表示数据组数. 接下来T行为询问,每行包含一个正整数N. T<=5000,N<=10^7 输出 按读入顺序输出答案. 样例输入 1 10 样例输出 136 题解 欧拉函数 其中用到了 这个推导很简单:由欧拉函数的定义,$\sum\limits_{i=1}^k\sum\limits_{j=1}^i[\gcd(i,j)=1]=\sum\limits_{i=1}^k\varphi(i)$,此时$i\ge j$,而当$i\le j$时情况相同.最后

容斥原理、欧拉函数、phi

容斥原理: 直接摘用百度词条: 也可表示为 设S为有限集, ,则 两个集合的容斥关系公式:A∪B = A+B - A∩B (∩:重合的部分) 三个集合的容斥关系公式:A∪B∪C = A+B+C - A∩B - B∩C - C∩A +A∩B∩C 详细推理如下: 1. 等式右边改造 = {[(A+B - A∩B)+C - B∩C] - C∩A }+ A∩B∩C 2.文氏图分块标记如右图图:1245构成A,2356构成B,4567构成C 3.等式右边()里指的是下图的1+2+3+4+5+6六部分: 那

UVa 10214 (莫比乌斯反演 or 欧拉函数) Trees in a Wood.

题意: 这道题和POJ 3090很相似,求|x|≤a,|y|≤b 中站在原点可见的整点的个数K,所有的整点个数为N(除去原点),求K/N 分析: 坐标轴上有四个可见的点,因为每个象限可见的点数都是一样的,所以我们只要求出第一象限可见的点数然后×4+4,即是K. 可见的点满足gcd(x, y) = 1,于是将问题转化为x∈[1, a], y∈[1, b],求gcd(x, y) = 1的个数. 类比HDU 1695可以用莫比乌斯反演来做,我还写了普通的和分块加速的两份代码,交上去发现运行时间相差并不

欧拉函数

void Euler_Sieve_Method(int * euler, int n) { euler[1] = 1; for (int i = 2; i < n; i++) { euler[i] = i; } for (int i = 2; i < n; i++) { if (euler[i] == i) { for (int j = i; j < n; j += i) { euler[j] = euler[j] / i * (i - 1); } } } } void Euler_Si

hdu1695(莫比乌斯)或欧拉函数+容斥

题意:求1-b和1-d之内各选一个数组成数对,问最大公约数为k的数对有多少个,数对是有序的.(b,d,k<=100000) 解法1: 这个可以简化成1-b/k 和1-d/k 的互质有序数对的个数.假设b=b/k,d=d/k,b<=d.欧拉函数可以算出1-b与1-b之内的互质对数,然后在b+1到d的数i,求每个i在1-b之间有多少互质的数.解法是容斥,getans函数参数的意义:1-tool中含有rem位置之后的i的质因子的数的个数. 在 for(int j=rem;j<=factor[i