博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
hdu 4676 Sum Of Gcd 莫队+phi反演
阅读量:4336 次
发布时间:2019-06-07

本文共 2947 字,大约阅读时间需要 9 分钟。

Sum Of Gcd

题目连接:

Description

Given you a sequence of number a1, a2, ..., an, which is a permutation of 1...n.

You need to answer some queries, each with the following format:
Give you two numbers L, R, you should calculate sum of gcd(a[i], a[j]) for every L <= i < j <= R.

Input

First line contains a number T(T <= 10),denote the number of test cases.

Then follow T test cases.
For each test cases,the first line contains a number n(1<=n<= 20000).
The second line contains n number a1,a2,...,an.
The third line contains a number Q(1<=Q<=20000) denoting the number of queries.
Then Q lines follows,each lines contains two integer L,R(1<=L<=R<=n),denote a query.

Output

For each case, first you should print "Case #x:", where x indicates the case number between 1 and T.

Then for each query print the answer in one line.

Sample Input

1

5
3 2 5 4 1
3
1 5
2 4
3 3

Sample Output

Case #1:

11
4
0

Hint

题意

给你n个数,然后Q次询问,每次问你l,r区间的两两之间的GCD和是多少

题解:

莫队+反演,直接暴力莽就好了……

代码

#include 
using namespace std;const int maxn = 2e4 + 15;int unit , a[maxn] , N , M , cnt[maxn];long long ans[maxn] , phi[maxn];vector < int > factor[maxn];struct Query{ int l , r , idx; friend bool operator < (const Query & a , const Query & b){ int x1 = a.l / unit , x2 = b.l / unit; if( x1 != x2 ) return x1 < x2; return a.r < b.r; }}Q[maxn];void Init(){ for(int i = 1 ; i < maxn ; ++ i) for(int j = i ; j < maxn ; j += i) factor[j].push_back( i ); phi[1] = 1; for(int i = 2 ; i < maxn ; ++ i) if( !phi[i] ) for(int j = i ; j < maxn ; j += i){ if( !phi[j] ) phi[j] = j; phi[j] = phi[j] * ( i - 1 ) / i; }}long long add( int x ){ long long res = 0; for( auto d : factor[x] ) res += cnt[d] * phi[d]; for( auto d : factor[x] ) cnt[d] ++ ; return res;}long long del( int x ){ long long res = 0; for( auto d : factor[x] ) cnt[d] -- ; for( auto d : factor[x] ) res += cnt[d] * phi[d]; return -res;}void solve(){ memset( cnt , 0 , sizeof( cnt ) ); int l = 1 , r = 0; long long cur = 0; for(int i = 1 ; i <= M ; ++ i){ while( l < Q[i].l ) cur += del( a[l++] ); while( l > Q[i].l ) cur += add( a[--l] ); while( r < Q[i].r ) cur += add( a[++r] ); while( r > Q[i].r ) cur += del( a[r--] ); ans[Q[i].idx] = cur; }}int main( int argc , char * argv[] ){ Init(); int Case , cas = 0; scanf("%d",&Case); while(Case--){ scanf("%d",&N); for(int i = 1 ; i <= N ; ++ i) scanf("%d" , a + i); scanf("%d",&M); for(int i = 1 ; i <= M ; ++ i){ Q[i].idx = i; scanf("%d%d",&Q[i].l,&Q[i].r); } unit = sqrt( N ); sort( Q + 1 , Q + M + 1 ); solve(); printf("Case #%d:\n" , ++ cas); for(int i = 1 ; i <= M ; ++ i) printf("%lld\n" , ans[i]); } return 0;}

转载于:https://www.cnblogs.com/qscqesze/p/5493685.html

你可能感兴趣的文章
python-9-IO编程
查看>>
【GoLang】转载:我为什么放弃Go语言,哈哈
查看>>
【MySQL】MySQL 如何实现 唯一随机数ID
查看>>
【Redis】Redis分布式集群几点说道
查看>>
HDU2819(KB10-E 二分图最大匹配)
查看>>
mysql主从复制、redis基础、持久化和主从复制
查看>>
文档工具GitBook使用
查看>>
两个链表的第一个公共节点
查看>>
知道这20个正则表达式,能让你少写1,000行代码
查看>>
Digit Sum II( ABC044&ARC060)
查看>>
【原创】Kakfa metrics包源代码分析
查看>>
MariaDB 主从同步与热备(14)
查看>>
推荐的 CSS 书写顺序
查看>>
NIO:与 Buffer 一起使用 Channel
查看>>
Android帧缓冲区(Frame Buffer)硬件抽象层(HAL)模块Gralloc的实现原理分析
查看>>
Android - 广播机制和Service
查看>>
MFC接收ShellExecute多个参数
查看>>
volatile和synchronized的区别
查看>>
RocketMQ介绍与云服务器安装
查看>>
课上动手动脑
查看>>