●BZOJ 3529 [Sdoi2014]数表
题链:
http://www.lydsy.com/JudgeOnline/problem.php?id=3529
题解:
莫比乌斯反演。
按题目的意思,令$f(i)$表示i的所有约数的和,就是要求:
$ANS=\sum f(gcd(i,j)),满足1 \leq i \leq n,1 \leq j \leq m,且 f(gcd(i,j))\leq a$
首先 $f(i)$ 应该还是比较好推的,利用其为积性函数的特点,可以在线性筛时完成计算。
令$g[k]$表示$gcd(i,j)=k$的$(i,j)$的对数
$G[k]$表示$gcd(i,j)=\lambda k$的$(i,j)$的对数,其值$G[k]=\lfloor \frac{n}{k} \rfloor \lfloor \frac{m}{k} \rfloor$
那么显然,$G[k]$为$g[k]$的倍数关系和函数,
即满足$G[k]=\sum_{k|d} g[d]$
则由莫比乌斯反演得:
$g[k]=\sum_{k|d}\mu(\frac{d}{k})G[d]$
$\quad\quad=\sum_{k|d}\mu(\frac{d}{k})\lfloor \frac{n}{d} \rfloor \lfloor \frac{m}{d} \rfloor$
那么现在,直接从gcd的值的角度出发,ANS可以写成如下形式:
$ANS=\sum_{i=1}^{min(n,m)}f(i)g(i)$
$\quad\quad=\sum_{i=1}^{min(n,m)}f(i)\sum_{i|d}\mu(\frac{d}{i})\lfloor \frac{n}{d} \rfloor \lfloor \frac{m}{d} \rfloor$
然后再化一下:
$\quad\quad=\sum_{d=1}^{min(n,m)}\lfloor \frac{n}{d} \rfloor \lfloor \frac{m}{d} \rfloor\sum_{i|d}f(i)\mu(\frac{d}{i})$
令 $w(d)=\sum_{i|d}f(i)\mu(\frac{d}{i})$
那么$ANS=\sum_{d=1}^{min(n,m)}\lfloor \frac{n}{d} \rfloor \lfloor \frac{m}{d} \rfloor w(d)$
如果不考虑题目中$f(gcd(i,j))\leq a$的限制
我们就可以枚举每个i,然后把其倍数$d=\lambda i$的$w(d)+=f(i)\mu(\frac{d}{i})$
以此计算出所有的w(d),复杂度为O(Nlog_2N)的。
然后那个求ANS的式子就可以运用向下取整的特性进行分块计算,就可以达到每个询问$O(\sqrt N)$的复杂度。
再来考虑有a的限制时的做法,(其实也不麻烦)
离线询问,按a从小到大排序,
同时把f(i)按从小到大排序,
一次遍历每个询问,并把$f(i)$小于当前询问的$a$的$i$按之前的做法:枚举倍数,加入对应的$w(d)$。
但是为了维护好前缀和,以便使用分块计算,
所以用树状数组维护,即把值$f(i)\mu(\frac{d}{i})$加入到树状数组里面。
然后同样的用树状数组查询前缀和就可以继续对当前询问进行分块计算了。
复杂度:
- #include<cstdio>
- #include<cstring>
- #include<iostream>
- #include<algorithm>
- #define MAXN 100050
- using namespace std;
- struct BIT{
- int val[MAXN],N;
- void Reset(int n){memset(val,0,sizeof(val));N=n;}
- int Lowbit(int p){return p&-p;}
- void Modify(int p,int v){
- while(p<=N) val[p]+=v,p+=Lowbit(p);
- }
- int Query(int p,int ret=0){
- while(p) ret+=val[p],p-=Lowbit(p);
- return ret;
- }
- }DT;
- struct Question{
- int n,m,a,id;
- friend bool operator < (Question A,Question B){
- return A.a<B.a;
- }
- }Q[MAXN];
- int f[MAXN],fi[MAXN],mu[MAXN],ANS[MAXN];
- bool cmp(int i,int j){
- return f[i]<f[j];
- }
- void Sieve(){
- static bool np[MAXN];
- static int prime[MAXN],pnt,tmp;
- mu[1]=f[1]=fi[1]=1;
- for(int i=2;i<=100000;i++){
- fi[i]=i;
- if(!np[i]) prime[++pnt]=i,mu[i]=-1,f[i]=1+i;
- for(int j=1;j<=pnt&&i<=100000/prime[j];j++){
- np[i*prime[j]]=1;
- if(i%prime[j]){
- mu[i*prime[j]]=-mu[i];
- f[i*prime[j]]=f[i]*f[prime[j]];
- }
- else{
- mu[i*prime[j]]=0;
- tmp=i; while(!(tmp%prime[j])) tmp=tmp/prime[j];
- f[i*prime[j]]=f[i]*prime[j]+f[tmp];
- }
- if(i%prime[j]==0) break;
- }
- }
- sort(fi+1,fi+100000+1,cmp);
- }
- int main(){
- Sieve(); int Case,ret,mini,n,m;
- scanf("%d",&Case);
- DT.Reset(100000);
- for(int i=1;i<=Case;i++)
- scanf("%d%d%d",&Q[i].n,&Q[i].m,&Q[i].a),Q[i].id=i;
- sort(Q+1,Q+Case+1);
- for(int q=1,p=1;q<=Case;q++){
- while(p<=100000&&f[fi[p]]<=Q[q].a){
- for(int d=fi[p];d<=100000;d+=fi[p])
- DT.Modify(d,f[fi[p]]*mu[d/fi[p]]);
- p++;
- }
- ret=0; n=Q[q].n; m=Q[q].m; mini=min(n,m);
- for(int i=1,last;i<=mini;i=last+1){
- last=min(n/(n/i),m/(m/i));
- ret+=(DT.Query(last)-DT.Query(i-1))*(n/i)*(m/i);
- }
- ANS[Q[q].id]=ret;
- }
- for(int i=1;i<=Case;i++)
- printf("%d\n",ANS[i]&(int)((1ll<<31)-1));
- return 0;
- }
●BZOJ 3529 [Sdoi2014]数表的更多相关文章
- BZOJ 3529: [Sdoi2014]数表 [莫比乌斯反演 树状数组]
3529: [Sdoi2014]数表 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 1399 Solved: 694[Submit][Status] ...
- bzoj 3529 [Sdoi2014]数表(莫比乌斯反演+BIT)
Description 有一张N×m的数表,其第i行第j列(1 < =i < =礼,1 < =j < =m)的数值为能同时整除i和j的所有自然数之和.给定a,计算数表中不大于a ...
- 【刷题】BZOJ 3529 [Sdoi2014]数表
Description 有一张n×m的数表,其第i行第j列(1<=i<=n,1<=j<=m)的数值为能同时整除i和j的所有自然数之和.给定a,计算数表中不大于a的数之和. In ...
- BZOJ 3529 [Sdoi2014]数表 (莫比乌斯反演+树状数组+离线)
题目大意:有一张$n*m$的数表,第$i$行第$j$列的数是同时能整除$i,j$的所有数之和,求数表内所有不大于A的数之和 先是看错题了...接着看对题了发现不会做了...刚了大半个下午无果 看了Po ...
- bzoj 3529: [Sdoi2014]数表
#include<cstdio> #include<iostream> #include<algorithm> #define M 200009 //#define ...
- BZOJ 3529 [Sdoi2014]数表 ——莫比乌斯反演 树状数组
$ans=\sum_{i=1}^n\sum_{j=1}^n\sigma(gcd(i,j))$ 枚举gcd为d的所有数得到 $ans=\sum_{d<=n}\sigma(d)*g(d)$ $g(d ...
- BZOJ 3259 [Sdoi2014]数表 (莫比乌斯反演 + 树状数组)
3529: [Sdoi2014]数表 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 2321 Solved: 1187[Submit][Status ...
- 3529: [Sdoi2014]数表 - BZOJ
Description 有一张N×m的数表,其第i行第j列(1 < =i < =n,1 < =j < =m)的数值为能同时整除i和j的所有自然数之和.给定a,计算数表中不大于a ...
- 【BZOJ】3529: [Sdoi2014]数表
题意:求 $$\sum_{i=1}^{n} \sum_{j=1}^{m} \sum_{d|(i, j)} d 且 (\sum_{d|(i, j)} d)<=a$$ n, m<=1e5,q次 ...
随机推荐
- 201621123050 《Java程序设计》第14周学习总结
1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结与数据库相关内容. 2. 使用数据库技术改造你的系统 2.1 简述如何使用数据库技术改造你的系统.要建立什么表?截图你的表设计. 答 ...
- mongodb 集群分片
分片 在Mongodb里面存在另一种集群,就是分片技术,可以满足MongoDB数据量大量增长的需求 当MongoDB存储海量的数据时,一台机器可能不足以存储数据,也可能不足以提供可接受的读写吞吐量,这 ...
- javascript实现小鸟飞行轨迹
javascript实现小鸟飞行轨迹 代码如下:
- 我的PCB电路设计(一)
我的制板规则 过孔大小:14/24mil-(12/22-28/50) 一般过孔没必要太大.如果电流较大可以适当增大过孔,或者多加几个过孔 线宽大小:小信号线8mil,大电流线不等按1A电流30mil ...
- vue jsx 使用指南
vue jsx 使用指南 vue jsx 语法与 react jsx 还是有些不一样,在这里记录下. let component = null // if 语句 if (true) { compone ...
- Python内置函数(29)——slice
英文文档: class slice(stop) class slice(start, stop[, step]) Return a slice object representing the set ...
- 使用Putty实现windows向阿里云的Linux云服务器上传文件
1.首先获取PSCP工具 PuTTY小巧方便.但若需要向网络中的Linux系统上传文件,则可以使用PuTTY官方提供的PSCP工具来实现上传.PSCP是基于ssh协议实现. 可以点击这里下载 2.启动 ...
- 网络IO超时的几种实现
一.select/poll/epoll int select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,str ...
- leetcode算法:Reshape the Matrix
In MATLAB, there is a very useful function called 'reshape', which can reshape a matrix into a new o ...
- Python之进程
进程 进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础.在早期面向进程设计的计算机结构中,进程是程序的基本执行实体:在当代 ...