UESTC - 1724 GCD区间求和

依然是神奇的欧拉函数

若GCD(n,i)=k

则GCD(n/k,i/k)=1,

令i/k=x,有GCD(n/k,x)=1,

→k*GCD(n/k,x)=1中x的个数 = GCD(n,i)=k的和

范围就是求n的所有因子k

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e6+11;
typedef unsigned long long ll;
ll phi[maxn];
void euler(int n){
    for(int i = 1; i <= n; i++){
        phi[i]=i;
    }
    for(int i = 2; i <= n; i++){
        if(phi[i]==i){
            for(int j = i; j <= n; j+=i){
                phi[j]=phi[j]/i*(i-1);
            }
        }
    }
}
vector<int> P;
void chai(int n){
    P.clear();
    for(ll i = 1; i*i <= n; i++){
        if(n%i==0){
            P.push_back(i);
            if(n/i!=i) P.push_back(n/i);
        }
    }
}
int a[maxn],n;
int main(){
    euler(maxn-1);
    while(scanf("%d",&n)!=EOF){
        ll ans=0;
        for(int i = 1; i <= n; i++) scanf("%d",&a[i]);
        for(int i = 1; i <= n; i++){
            chai(a[i]);
            for(int j = 0; j < P.size(); j++){
                ans+=phi[a[i]/P[j]]*P[j];
            }
            ans-=a[i];
        }
        printf("%llu\n",ans);
    }
    return 0;
}

原文地址:https://www.cnblogs.com/caturra/p/8271095.html

时间: 2024-10-05 17:33:25

UESTC - 1724 GCD区间求和的相关文章

区间求和

区间求和 基准时间限制:1 秒 空间限制:131072 KB 分值: 80 LYK在研究一个有趣的东西. 假如有一个长度为n的序列,那么这个序列的权值将是所有有序二元组i,j的 Σaj−ai 其中1<=i<j<=n. 但是这个问题似乎太简单了. 于是LYK想在所有有序二元组k,l中若ak=al,其中1<=k<l<=n,则将 a{k},a{k+1},...,a{l}  提出当做一个序列,计算它的权值. 并统计所有这样的区间的权值和. 由于答案可能很大,你只需要将答案对2^

HDU4027 Can you answer these queries 线段树区间求和+剪枝

给了你n,然后n个数字在一个数组中,接下来m个询问,每个询问三个数字 t,x,y,若t==0,那么修改区间[x,y]的每一个值,变为原来每个位置上的数 开根号取整,若t==1,那么对区间[x,y]求和 由于n,m,很大,所以树状数组铁定超时,若直接用线段树来做区间修改,那么也是超时,这类题目没别的方法了,静心剪枝,发现题目给的数据范围为2^63,有没有发现,2^63开根号 绝对不需要开10次,就能到1,到1以后就不需要再开了,意思就是若有某个区间[x,y]每一个点的值都为1时,这一段区间事实上是

【线段树(单点修改,区间求和)】HDU1166 - 敌军布阵

hdu1166 敌兵布阵,单点修改,区间求和. [ATTENTION]MAXN要开成节点数的4倍,开得不够会提示TLE. 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #define lson l,m,root<<1 5 #define rson m+1,r,root<<1|1 6 using namespace std; 7 const int MAXN=50000*

算法模板——线段树3(区间覆盖值+区间求和)

实现功能——1:区间覆盖值:2:区间求和 相比直接的区间加,这个要注重顺序,因为操作有顺序之分.所以这里面的tag应该有个pushup操作(本程序中的ext) 1 var 2 i,j,k,l,m,n,a1,a2,a3,a4:longint; 3 a,b,d:array[0..100000] of longint; 4 function max(x,y:longint):longint;inline; 5 begin 6 if x>y then max:=x else max:=y; 7 end;

算法模板——线段树4(区间加+区间乘+区间覆盖值+区间求和)

实现功能——1:区间加法 2:区间乘法 3:区间覆盖值 4:区间求和 这是个四种常见线段树功能的集合版哦...么么哒(其实只要协调好三种tag的关系并不算太难——前提是想明白了线段树的工作模式) 代码长度几经修改后也大为缩水 还有!!!——通过BZOJ1798反复的尝试,我的出来一个重要结论——尽量减少pushup操作的不必要使用次数,对于程序提速有明显的效果!!! 1 type vet=record 2 a0,a1:longint; 3 end; 4 var 5 i,j,k,l,m,n,a1,

算法模板——线段树1(区间加法+区间求和)

实现功能——1:区间加法:2:区间求和 最基础最经典的线段树模板.由于这里面操作无顺序之分,所以不需要向下pushup,直接累积即可 1 var 2 i,j,k,l,m,n,a1,a2,a3,a4:longint; 3 a,b:array[0..100000] of longint; 4 function max(x,y:longint):longint;inline; 5 begin 6 if x>y then max:=x else max:=y; 7 end; 8 function min

vijos1740 聪明的质监员 (二分、区间求和)

http://www.rqnoj.cn/problem/657 https://www.vijos.org/p/1740 P1740聪明的质检员 请登录后递交 标签:NOIP提高组2011[显示标签] 描述 小 T 是一名质量监督员,最近负责检验一批矿产的质量.这批矿产共有n个矿石,从1到n逐一编号,每个矿石都有自己的重量wi以及价值vi.检验矿产的流程是: 1.给定m个区间[Li,Ri]: 2.选出一个参数W: 3.对于一个区间[Li,Ri],计算矿石在这个区间上的检验值Yi: Yi = ∑1

CodeForces 52C Circular RMQ(区间循环线段树,区间更新,区间求和)

转载请注明出处:http://blog.csdn.net/u012860063 题目链接:http://codeforces.com/problemset/problem/52/C You are given circular array a0,?a1,?...,?an?-?1. There are two types of operations with it: inc(lf,?rg,?v) - this operation increases each element on the segm

[用CDQ分治解决区间加&amp;区间求和]【习作】

[前言] 作为一个什么数据结构都不会只会CDQ分治和分块的蒟蒻,面对区间加&区间求和这么难的问题,怎么可能会写线段树呢 于是,用CDQ分治解决区间加&区间求和这篇习作应运而生 [Part.I]区间加&区间求和的数据结构做法 [一]线段树 裸题... 1141ms #include <iostream> #include <cstdio> #include <algorithm> #include <cstring> #include