• 博客园logo
  • 会员
  • 周边
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • YouClaw
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
HaibaraAi
博客园    首页    新随笔    联系   管理    订阅  订阅

HDU 4676 Sum Of Gcd

Sum Of Gcd

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)
Total Submission(s): 405    Accepted Submission(s): 194


做了2013杭州的H题后回头看了下这题,发现之前根本不懂- -!
这题也是离线,好想要分块,就是那个sqrt(1.0*n)和lx[i].c=lx[i].l/d;和cmp
其他的用了个公式sigama(num[i],2)*euler[i];
公式中的num意义为能整除每个因子的数的个数
num[i],l to r 中i能整除i的个数,euler[i]为i的欧拉函数!
后面的是指num[vt[a[i]][j]],也就是能整除vt[a[i]][j]的个数和euler[vt[a[i]][j]];
这其实把num[i]*(num[i]-1)/2;这个等差求和的公式化回去,就相当于从0开始一个一个加
这题也要预处理因子,有那个因子就num[v]++;删的时候就num[v]--;便于整体相加求和!,然后按l排序,从左到右加过去,进行删补就可以了!
Problem 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
 

 

Source
2013 Multi-University Training Contest 8
 

 

Recommend
zhuyuanchen520   |   We have carefully selected several similar problems for you:  4769 4767 4766 4765 4763 
 

 

Statistic | Submit | Discuss | Note
  1 #pragma comment(linker, "/STACK:1024000000,1024000000")
  2 #include <map>
  3 #include <queue>
  4 #include <vector>
  5 #include <string>
  6 #include <cmath>
  7 #include <cstdio>
  8 #include <cstring>
  9 #include <cstdlib>
 10 #include <iostream>
 11 #include <algorithm>
 12 using namespace std;
 13 #define maxn 20005
 14 #define ll long long
 15 #define INF 0x7fffffff
 16 #define eps 1e-8
 17 struct line{int l, r,p,c;};
 18 int n, m, k,x,y,res;
 19 vector<int>p[maxn];
 20 line lx[maxn];
 21 int euler[maxn];
 22 int num[maxn];
 23 int ans[maxn];
 24 int a[maxn];
 25 void init(){
 26     for (int i = 1; i < maxn; i++)euler[i] = i;
 27     for (int i = 2; i < maxn; i++)
 28     if (euler[i] == i)
 29     for (int j = i; j < maxn; j += i)
 30         euler[j] = euler[j] / i*(i - 1);
 31     for (int i = 1; i < maxn; i++){
 32         p[i].clear();
 33         for (int j = 1; j*j <= i; j++)
 34         if (i%j == 0){
 35             p[i].push_back(j);
 36             if (j*j!=i)p[i].push_back(i / j);
 37         }
 38     }
 39 }
 40 int query(int l, int r){
 41     for (int i = l; i < x; i++)
 42     for (int j = 0; j < p[a[i]].size(); j++){
 43         k = p[a[i]][j];
 44         res += euler[k] * num[k];
 45         num[k]++;
 46     }
 47     for (int i = x; i < l; i++)
 48     for (int j = 0; j < p[a[i]].size(); j++){
 49         k = p[a[i]][j];
 50         num[k]--;
 51         res -= euler[k] * num[k];
 52     }
 53     for (int i = r+1; i <= y; i++)
 54     for (int j = 0; j < p[a[i]].size(); j++){
 55         k = p[a[i]][j];
 56         num[k]--;
 57         res -= euler[k] * num[k];
 58     }
 59     for (int i = y+1; i <= r; i++)
 60     for (int j = 0; j < p[a[i]].size(); j++){
 61         k = p[a[i]][j];
 62         res += euler[k] * num[k];
 63         num[k]++;
 64     }
 65     x = l; y = r;
 66     return res;
 67 }
 68 int cmp(line a, line b){
 69     if (a.c == b.c)return a.r < b.r;
 70     return a.c < b.c;
 71 }
 72 int main(){
 73     int cas = 1;
 74     init();
 75     int t;
 76     scanf("%d", &t);
 77     while (t--){
 78         scanf("%d", &n);
 79         memset(num, 0, sizeof num);
 80         for (int i = 1; i <= n; i++)scanf("%d", &a[i]);
 81         scanf("%d", &m);
 82         int d = sqrt(1.0*n);
 83         for (int i = 0; i < m; i++){
 84             scanf("%d%d", &lx[i].l, &lx[i].r);
 85             lx[i].c = lx[i].l / d;
 86             lx[i].p = i;
 87         }
 88         sort(lx, lx + m, cmp);
 89         res = 0;
 90         x = lx[0].l; y = lx[0].r;
 91         for (int i = x; i <= y; i++)
 92         for (int j = 0; j < p[a[i]].size(); j++){
 93             k = p[a[i]][j];
 94             res += euler[k] * num[k];
 95             num[k]++;
 96         }
 97         ans[lx[0].p] = res;
 98         for (int i = 1; i < m; i++)ans[lx[i].p] = query(lx[i].l, lx[i].r);
 99         printf("Case #%d:\n", cas++);
100         for (int i = 0; i < m;i++)printf("%d\n", ans[i]);
101     }
102     return 0;
103 }
View Code
posted @ 2013-10-28 19:17  HaibaraAi  阅读(132)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2026
浙公网安备 33010602011771号 浙ICP备2021040463号-3