HDU4767_Sum Of Gcd
通过一个题目,学到了很多。
题意为给你n个数,每次询问i,j,答案为i,j间任取两数所有的取法gcd的和。
假设我们当前要看看这个区间有多少个数的gcd为x,最最原始的想法都是查询这个区间有多少个数为x的倍数。然后任取两个%&*¥#@!,但是有的gcd不是x,而是x的倍数。
这个问题这样来考虑,其实思想上是莫比乌斯反演。
假设当前我们有x个数是要求的现在的数y的倍数,那么所有的y的约数也肯定包含了这x个数。
所以我们可以当前要乘以的这个数不是x,而是一个f[x],显然x的所有的约数的函数和为x,这样就保证了求解的正确性。
同时想到了这里就会发现,所求的函数值与原题给的数据和各个数字的位置关系是没有关系的了,可以预处理。
最后看过各种,终于学到了,这个函数值就是欧拉函数值。 神坑啊。
还有就是这里的区间求解有一个小小的技巧。
区间分块处理,什么意思呢?
把区间排序,每次按照区间左端点所在的区进行排序,如果在同一区的话,就按右端点来排序,这样就保证了更新的复杂度为n*sqrt(n)。
真心受教了,不过鄙人还是觉得这种做法不太严谨,感觉如果是这个题目有极限数据的话,还是会T,不过确实比我想过的所有其他的想法都要优。
数论又一次被虐了。。。。。。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
#include <cmath>
#define maxn 20002
typedef long long ll;
using namespace std; vector<int> g[maxn];
ll sum[maxn],ans;
int num[maxn],a[maxn],phi[maxn],t,n,m,Q,cas=,curl,curr; struct query{
int li,ri,pos;
}q[maxn]; bool cmp(query q1,query q2)
{
int l1=q1.li/m,l2=q2.li/m;
if (l1==l2) return q1.ri<q2.ri;
return q1.li<q2.li;
} void init()
{
for (int i=; i<maxn; i++)
for (int j=i; j<maxn; j+=i) g[j].push_back(i);
phi[]=;
for (int i=; i<maxn; i++)
{
if (phi[i]==) phi[i]=i;
else continue;
for (int j=i; j<maxn; j+=i)
{
if (phi[j]==) phi[j]=j;
phi[j]=phi[j]/i*(i-);
}
}
} void add(int x,int tag)
{
for (unsigned i=; i<g[x].size(); i++)
{
int k=g[x][i];
if (tag==-) num[k]--;
ans+=(ll)tag*num[k]*phi[k];
if (tag== ) num[k]++;
}
} void _process()
{
ans=;
memset(num,,sizeof num);
curl=q[].li,curr=q[].ri;
for (int i=curl; i<=curr; i++) add(a[i],);
sum[q[].pos]=ans;
for (int i=; i<=Q; i++)
{
while (curl<q[i].li) add(a[curl],-),curl++;
while (curr>q[i].ri) add(a[curr],-),curr--;
while (curl>q[i].li) add(a[--curl], );
while (curr<q[i].ri) add(a[++curr], );
sum[q[i].pos]=ans;
}
} int main()
{
init();
scanf("%d",&t);
while (t--)
{
scanf("%d",&n); m=(int)sqrt(n+0.5);
for (int i=; i<=n; i++) scanf("%d",&a[i]);
scanf("%d",&Q);
for (int i=; i<=Q; i++) scanf("%d%d",&q[i].li,&q[i].ri),q[i].pos=i;
sort(q+,q++Q,cmp);
_process();
printf("Case #%d:\n",++cas);
for (int i=; i<=Q; i++) printf("%I64d\n",sum[i]);
}
return ;
}
HDU4767_Sum Of Gcd的更多相关文章
- Objective-C三种定时器CADisplayLink / NSTimer / GCD的使用
OC中的三种定时器:CADisplayLink.NSTimer.GCD 我们先来看看CADiskplayLink, 点进头文件里面看看, 用注释来说明下 @interface CADisplayLin ...
- iOS 多线程之GCD的使用
在iOS开发中,遇到耗时操作,我们经常用到多线程技术.Grand Central Dispatch (GCD)是Apple开发的一个多核编程的解决方法,只需定义想要执行的任务,然后添加到适当的调度队列 ...
- 【swift】BlockOperation和GCD实用代码块
//BlockOperation // // ViewController.swift import UIKit class ViewController: UIViewController { @I ...
- 修改版: 小伙,多线程(GCD)看我就够了,骗你没好处!
多线程(英语:multithreading),是指从软件或者硬件上实现多个线程并发执行的技术.具有多线程能力的计算机因有硬件支持而能够在同一时间执行多于一个线程,进而提升整体处理性能.具有这种能力的系 ...
- GCD的相关函数使用
GCD 是iOS多线程实现方案之一,非常常用 英文翻译过来就是伟大的中枢调度器,也有人戏称为是牛逼的中枢调度器 是苹果公司为多核的并行运算提出的解决方案 1.一次性函数 dispatch_once 顾 ...
- hdu1695 GCD(莫比乌斯反演)
题意:求(1,b)区间和(1,d)区间里面gcd(x, y) = k的数的对数(1<=x<=b , 1<= y <= d). 知识点: 莫比乌斯反演/*12*/ 线性筛求莫比乌 ...
- hdu2588 GCD (欧拉函数)
GCD 题意:输入N,M(2<=N<=1000000000, 1<=M<=N), 设1<=X<=N,求使gcd(X,N)>=M的X的个数. (文末有题) 知 ...
- BZOJ 2820: YY的GCD [莫比乌斯反演]【学习笔记】
2820: YY的GCD Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 1624 Solved: 853[Submit][Status][Discu ...
- BZOJ 2818: Gcd [欧拉函数 质数 线性筛]【学习笔记】
2818: Gcd Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 4436 Solved: 1957[Submit][Status][Discuss ...
随机推荐
- sort与qsort的异同
主要内容: 1.qsort的用法 2.sort的用法 3.qsort和sort的区别 qsort的用法: 原 型: void qsort(void *base, int nelem, int widt ...
- apt-get 0%
错误如下: www.2cto.com 使用apt-get命令安装软件时出现“0%[正在等待报头]“的提示且无法继续安装,一般出现此问题是因为安装过程中Ctrl+C强行中断或其它原因导致上 ...
- PHP学习笔记之interface关键字
interface用于定义接口 接口里边的方法不需要有方法的实现 implements用于表示类实现某个接口 实现了某个接口之后,必须提供接口中定义的方法的具体实现. 可以用instanceof关键字 ...
- 搭建 ssm 环境
<!-- 引入外部jdbc配置文件 --> <context:property-placeholder location="classpath:dbconfig.prope ...
- C# TTS-文本转语音
System.Speech 命名空间包含支持语音识别的类型,你可以从Visual Studio很方便的添加相关组件的引用. System.Speech相关介绍:https://msdn.microso ...
- Codeforces Round #502 (in memory of Leopoldo Taravilse, Div. 1 + Div. 2) E. The Supersonic Rocket
这道题比赛之后被重新加了几个case,很多人现在都过不了了 算法就是先求凸包,然后判断两个凸包相等 我们可以吧凸包序列化为两点距离和角度 角度如果直接拿向量的叉积是不对的,,因为钝角和锐角的叉积有可能 ...
- 【洛谷】题解 P1056 【排座椅】
题目链接 因为题目说输入保证会交头接耳的同学前后相邻或者左右相邻,所以一对同学要分开有且只有一条唯一的通道才能把他们分开. 于是可以吧这条通道累加到一个数组里面.应为题目要求纵列的通道和横列的通道条数 ...
- 宿主机ssh免密登录docker容器
一.检查系统内核 二.安装docker 1.yum install docker -y 2.docker version #查看docker版本 3.syste ...
- 3D打印产业链全景图
- Scrum立会报告+燃尽图(十月十六日总第七次):总结工作经验,商讨未来策略
此作业要求参见:https://edu.cnblogs.com/campus/nenu/2018fall/homework/2197 Scrum立会master:李文涛 一.小组介绍 组长:付佳 组员 ...