BZOJ3259(莫比乌斯反演 + 树状数组 + 离散处理 + 极性函数)
来源:互联网 发布:二手交易软件排名 编辑:程序博客网 时间:2024/06/06 00:31
3529: [Sdoi2014]数表
Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 2049 Solved: 1027
[Submit][Status][Discuss]
Description
有一张N×m的数表,其第i行第j列(1 < =i < =礼,1 < =j < =m)的数值为
能同时整除i和j的所有自然数之和。给定a,计算数表中不大于a的数之和。
Input
输入包含多组数据。
输入的第一行一个整数Q表示测试点内的数据组数,接下来Q行,每行三个整数n,m,a(|a| < =10^9)描述一组数据。
Output
对每组数据,输出一行一个整数,表示答案模2^31的值。
Sample Input
2
4 4 3
10 10 5
4 4 3
10 10 5
Sample Output
20
148
148
HINT
1 < =N.m < =10^5 , 1 < =Q < =2×10^4
Source
Round 1 Day 1
解题思路:这题是莫比乌斯反演里面比较难得一个,首先要反演半天,得到一个公式,然后还要离线处理,最后还要用一个树状数组维护一下,中间的莫比乌斯函数和约数和函数都是积性函数,所以都可以线性筛。
#include <bits/stdc++.h>using namespace std;typedef long long LL;const int maxn = 100000 + 10;const unsigned int mod = (1<<31);struct query{ int N, M; int id; int A; bool operator <(const query &res) const { return A < res.A; }} Query[maxn];struct node{ int id; LL value;} Node[maxn];LL d[maxn];//约数和LL Tree[maxn];LL ans[maxn];int mu[maxn];bool valid[maxn];int prime[maxn];void Mobius(){ int tot = 0; memset(valid, true, sizeof(valid)); mu[1] = 1; d[1] = 1; for(int i = 2; i <= 100000; i++) { if(valid[i]) { prime[++tot] = i; d[i] = (LL)(i + 1); mu[i] = -1; } for(int j = 1; j <= tot && i * prime[j] <= 100000; j++) { valid[i * prime[j]] = false; if(i % prime[j] == 0) { mu[i * prime[j]] = 0; //d[i * prime[j]] = d[i] + (d[i] - d[i / prime[j]]) * prime[j]; int temp = i; while(temp % prime[j] == 0) { temp /= prime[j]; } d[i * prime[j]] = d[temp] + d[i] * prime[j]; break; } mu[i * prime[j]] = -mu[i]; d[i * prime[j]] = d[i] * (prime[j] + 1); } }}int lowbit(int x){ return x&(-x);}void add(int loc, LL value){ for(int i = loc; i <= 100000; i += lowbit(i)) { Tree[i] += value; Tree[i] %= mod; }}LL get(int loc){ LL sum = 0; for(int i = loc; i >= 1; i -= lowbit(i)) { sum += Tree[i]; sum %= mod; } return sum;}void init(){ memset(Tree, 0, sizeof(Tree)); memset(ans, 0, sizeof(ans));}bool cmp(node n1, node n2){ return n1.value < n2.value;}int Q;int main(){ //freopen("C:\\Users\\creator\\Desktop\\in1.txt","r",stdin) ; //freopen("C:\\Users\\creator\\Desktop\\out.txt","w",stdout) ; Mobius(); for(int i = 1; i <= 100000; i++) { Node[i].id = i; Node[i].value = d[i]; } sort(Node + 1, Node + 100001, cmp); scanf("%d", &Q); init(); for(int i = 1; i <= Q; i++) { scanf("%d%d%d", &Query[i].N, &Query[i].M, &Query[i].A); Query[i].id = i; } sort(Query + 1, Query + Q + 1); int judge = 1; int L = 1; while(judge <= Q) { while(Node[L].value <= Query[judge].A && L <= 100000) { int id = Node[L].id; LL value = Node[L].value; for(int j = id; j <= 100000; j += id) { add(j, value * mu[j / id]); } L++; } int N = Query[judge].N; int M = Query[judge].M; LL term = 0; int Min = min(N, M); int last; for(int j = 1; j <= Min; j = last + 1) { last = min(min(N / (N / j), M / (M / j)), Min); term = (term + (N / j) * (M / j) * (get(last) - get(j - 1)) % mod + mod) % mod; } ans[Query[judge].id] = term; judge++; } for(int i = 1; i <= Q; i++) { printf("%lld\n", ans[i]); } return 0;}
阅读全文
1 0
- BZOJ3259(莫比乌斯反演 + 树状数组 + 离散处理 + 极性函数)
- [BZOJ3529][Sdoi2014]数表 && 莫比乌斯反演+树状数组
- [BZOJ3529]SDOI2014数表|莫比乌斯反演|树状数组
- 3529: [Sdoi2014]数表 莫比乌斯反演+树状数组
- 3529: [Sdoi2014]数表|莫比乌斯反演|树状数组
- 【bzoj3529】【SDOI2014】【数表】【莫比乌斯反演+树状数组】
- [BZOJ3529] [SDOI2014] 数表 - 莫比乌斯反演 - 树状数组
- BZOJ 3529 莫比乌斯反演+树状数组
- HDU4947(莫比乌斯反演 + 树状数组维护)
- bzoj3529 [Sdoi2014]数表(莫比乌斯反演+树状数组)
- HDU-4947-GCD Array(树状数组+莫比乌斯反演)
- 【BZOJ】】【P3529】【Sdoi2014】【数表】【题解】【莫比乌斯反演+离线+树状数组】
- BZOJ 3529 SDOI2014 数表 莫比乌斯反演+树状数组
- 【bzoj3529】[Sdoi2014]数表 线性筛法+树状数组+莫比乌斯反演+数论分块
- bzoj 3529: [Sdoi2014]数表 莫比乌斯反演&树状数组
- [莫比乌斯反演 树状数组] BZOJ 3529 [Sdoi2014]数表
- bzoj 3529: [Sdoi2014]数表 莫比乌斯反演+树状数组
- [BZOJ3529][Sdoi2014]数表(莫比乌斯反演+树状数组)
- Thinkphp处理ueditor插入转义字符到数据库的方法
- 函数式与响应式的领域模型<Functional and Reactive Domain Modeling>(三)
- 170
- 内核基础层提供的服务---软中断和tasklet 、 工作队列
- matlab2c使用c++实现matlab函数系列教程-max函数
- BZOJ3259(莫比乌斯反演 + 树状数组 + 离散处理 + 极性函数)
- matlab2c使用c++实现matlab函数系列教程-min函数
- sublime的下载地址及Package Control的安装
- jquery-DOM操作
- 获取本机IP
- matlab2c使用c++实现matlab函数系列教程-mean函数
- Kafka 实例
- matlab2c使用c++实现matlab函数系列教程-median函数
- Tyvj1078