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

【BZOJ2005】[Noi2010]能量采集

Description

栋栋有一块长方形的地,他在地上种了一种能量植物,这种植物可以采集太阳光的能量。在这些植物采集能量后,栋栋再使用一个能量汇集机器把这些植物采集到的能量汇集到一起。 栋栋的植物种得非常整齐,一共有n列,每列有m棵,植物的横竖间距都一样,因此对于每一棵植物,栋栋可以用一个坐标(x, y)来表示,其中x的范围是1至n,表示是在第x列,y的范围是1至m,表示是在第x列的第y棵。 由于能量汇集机器较大,不便移动,栋栋将它放在了一个角上,坐标正好是(0, 0)。 能量汇集机器在汇集的过程中有一定的能量损失。如果一棵植物与能量汇集机器连接而成的线段上有k棵植物,则能量的损失为2k + 1。例如,当能量汇集机器收集坐标为(2, 4)的植物时,由于连接线段上存在一棵植物(1, 2),会产生3的能量损失。注意,如果一棵植物与能量汇集机器连接的线段上没有植物,则能量损失为1。现在要计算总的能量损失。 下面给出了一个能量采集的例子,其中n = 5,m = 4,一共有20棵植物,在每棵植物上标明了能量汇集机器收集它的能量时产生的能量损失。 在这个例子中,总共产生了36的能量损失。

Input

仅包含一行,为两个整数n和m。

Output

仅包含一个整数,表示总共产生的能量损失。

Sample Input

【样例输入1】
5 4
【样例输入2】
3 4

Sample Output

【样例输出1】
36
【样例输出2】
20
对于100%的数据:1 ≤ n, m ≤ 100,000。

题解

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
const int maxn=100010;
typedef long long ll;
int n,m,num;
int pri[maxn],phi[maxn],sm[maxn],np[maxn];
ll ans;
ll sp[maxn];
typedef long long ll;
int main()
{
	scanf("%d%d",&n,&m);
	if(n<m)	swap(n,m);
	int i,j,last;
	sp[1]=phi[1]=1;
	for(i=2;i<=n;i++)
	{
		if(!np[i])	pri[++num]=i,phi[i]=i-1;
		sp[i]=sp[i-1]+phi[i];
		for(j=1;j<=num&&i*pri[j]<=n;j++)
		{
			np[i*pri[j]]=1;
			if(i%pri[j]==0)
			{
				phi[i*pri[j]]=phi[i]*pri[j];
				break;
			}
			phi[i*pri[j]]=phi[i]*(pri[j]-1);
		}
	}
	for(i=1;i<=m;i=last+1)
	{
		last=min(n/(n/i),m/(m/i));
		ans+=1ll*(sp[last]-sp[i-1])*(n/i)*(m/i);
	}
	printf("%lld",2*ans-1ll*n*m);
	return 0;
}
时间: 2024-10-20 18:54:44

【BZOJ2005】[Noi2010]能量采集 欧拉函数的相关文章

[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>

【莫比乌斯反演】【线性筛】bzoj2005 [Noi2010]能量采集

http://blog.csdn.net/Clove_unique/article/details/51089272 Key:1.连接平面上某个整点(a,b)到原点的线段上有gcd(a,b)个整点. 2.欧拉函数的性质之一:若(N%a==0 && (N/a)%a==0) 则有:phi(N)=phi(N/a)*a.由此可以线性筛. 3.一个数的所有因子的phi值之和恰好等于这个数本身. #include<cstdio> #include<algorithm> usin

BZOJ2005: [Noi2010]能量采集 莫比乌斯反演的另一种方法——nlogn筛

分析:http://www.cnblogs.com/huhuuu/archive/2011/11/25/2263803.html 注:从这个题收获了两点 1,第一象限(x,y)到(0,0)的线段上整点的个数是gcd(x,y) 2,新学了一发求gcd(x,y)=k有多少对的姿势,已知0<x<=n,0<y<=m 令x=min(n,m),令f[i]代表gcd(x,y)=i的对数, 那么通过O(xlogx)的复杂度就可以得到f[1]到f[n](反着循环) 普通的容斥(即莫比乌斯反演)其实也

bzoj2005: [Noi2010]能量采集

[题意] 一块n*m大小的田,人站在(0,0)位置.对于每个(i,j)位置的植物,从(0,0)到(i,j)的连线中有k棵植物,能量损失就为2*k-1(包括端点上的植物).求所有植物的能量损失. n,m<=10^5 [题解] 实际上对于每棵植物k就是x坐标,y坐标的公约数,不过n*m棵植物显然不能一个个公约数求过来. 仔细想一下最大公约数d<=min(n,m),所以我们考虑枚举d并计算一下最大公约数为d的数对个数,这个值就设为f(d)好了. 首先直接(n/d)*(m/d)计算出来的只是公约数包含

【莫比乌斯反演】BZOJ2005 [NOI2010]能量采集

Description 求sigma gcd(x,y)*2-1,1<=x<=n, 1<=y<=m.n, m<=1e5. Solution f(n)为gcd正好是n的(x,y)的个数 F(n)为gcd是n的倍数的(x,y)的个数 我们要求的就是f(i) 然而这个不好直接算,可F(i)可以直接用(n/i)*(m/i)得到 那么有F(n)=sigma n|i f(i) 于是有f(n)=sigma n|i mu(i)*F(i) 这就是莫比乌斯反演,不过这道题直接用容斥的思想想也很容易

bzoj 2005: [Noi2010]能量采集 筛法||欧拉||莫比乌斯

2005: [Noi2010]能量采集 Time Limit: 10 Sec  Memory Limit: 552 MB[Submit][Status][Discuss] Description 栋栋有一块长方形的地,他在地上种了一种能量植物,这种植物可以采集太阳光的能量.在这些植物采集能量后, 栋栋再使用一个能量汇集机器把这些植物采集到的能量汇集到一起. 栋栋的植物种得非常整齐,一共有n列,每列 有m棵,植物的横竖间距都一样,因此对于每一棵植物,栋栋可以用一个坐标(x, y)来表示,其中x的范

欧拉函数

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

欧拉函数常用性质

欧拉函数定义:设n 为正整数,则1,2......,n中与n互质的整数个数记作f(n). 1.1 若n为素数,f(n)=n-1; 1.2 整数n=p*q,p,q为不同素数,则f(n)=f(p)*f(q)=(p-1)*(q-1) 1.3 n=p^a*q^b,f(n)=f(p^a)*f(q^b)=n*(1-1/p)*(1-1/q) 1.4 分解质因子相乘,f(n)=n*(1-1/p1)*(1-1/p2)*.......*(1-1/pk). f(100)=f(2^2*5^2)=100*1/2*4/5=