题目大意:有一张$n*m$的数表,第$i$行第$j$列的数是同时能整除$i,j$的所有数之和,求数表内所有不大于A的数之和

先是看错题了...接着看对题了发现不会做了...刚了大半个下午无果

看了Po姐的题解(Orzzz)才搞懂这道题,搞清楚了莫比乌斯反演的两种经典的卷积形式的不同之处

令$\sigma(i)$表示i的约数和

如果去掉A这个限制,则题目是让我们求$\sum_{i=1}^{n}\sum_{j=1}^{m}\sigma(gcd(i,j))$

考虑如何正确转化式子,让我们能够把不大于A这个限制加上去,再用某种数据结构快速维护,否则我们转化的式子就是失败的

令$f(i)$表示$i$作为$gcd$出现的次数,利用莫比乌斯反演的常规套路,可得$f(i)=\sum_{i|d}\mu(d/i)\left \lfloor \frac{n}{d} \right \rfloor\left \lfloor \frac{m}{d} \right \rfloor$

这样,再接下来的变形中,可以把d提到前面去,我们就能对d的范围进行限制了

那么结果$ans=\sum f(i)\sigma(i)$

展开得$ans=\sum_{i=1}^{n} \sigma(i)\sum_{i|d}\mu(d/i)\left \lfloor \frac{n}{d} \right \rfloor\left \lfloor \frac{m}{d} \right \rfloor$

移项$ans=\sum _{d=1}^{\sigma(d)<=A} \left \lfloor \frac{n}{d} \right \rfloor\left \lfloor \frac{m}{d} \right \rfloor \sum_{i|d}\mu(d/i)\sigma(i)$

对于前面的部分,对询问离线,按A从小到大排序,从小到大遍历即可$\sum _{d=1}^{\sigma(d)<=A} \left \lfloor \frac{n}{d} \right \rfloor\left \lfloor \frac{m}{d} \right \rfloor$

对于后面的部分$\sum_{i|d}\mu(d/i)\sigma(i)$当前询问的A大于等于$\sigma(i)$时,我们就要把i的贡献加进去,即所有能整除$i$的数的位置都要加上$\mu(d/i)\sigma(i)$

因为$\sigma(i)$并不具有单调性,所以需要用树状数组维护前缀和,可以暴力往树状数组里插入,因为总插入次数是$O(nlnn)$(调和级数)

接着对于每个询问,利用整除分块的思想求解即可

总时间$O(nlog^{2}n+Q\sqrt{n}logn)$,有点卡常,建议用unsigned int

 #include <cstdio>
#include <cstring>
#include <algorithm>
#define N 100100
#define maxn 100000
#define ll long long
#define uint unsigned int
using namespace std; const uint mod=2147483648ll;
int T,cnt;
int use[N],pr[N],mu[N],nxt[N];
uint sum[N];
ll sgm[N];
struct node{ll s;int id;}a[N];
int cmp1(node s1,node s2){return s1.s<s2.s;}
struct Ques{int n,m,A,id;ll ans;}Q[N];
int cmp2(Ques s1,Ques s2){return s1.A<s2.A;}
int cmp3(Ques s1,Ques s2){return s1.id<s2.id;} void update(int x,uint w){for(int i=x;i<=maxn;i+=(i&(-i)))(sum[i]+=w)%=mod;}
uint query(int x){uint ans=;for(int i=x;i>;i-=(i&(-i)))(ans+=sum[i])%=mod;return ans;}
void Pre()
{
mu[]=;
for(int i=;i<=maxn;i++)
{
if(!use[i]) pr[++cnt]=i,mu[i]=-,nxt[i]=i;
for(int j=;j<=cnt&&i*pr[j]<=maxn;j++){
use[i*pr[j]]=;
nxt[i*pr[j]]=pr[j];
if(i%pr[j]==){
mu[i*pr[j]]=;
break;
}else{
mu[i*pr[j]]=-mu[i];
}
}
}
for(int i=;i<=maxn;i++)
for(int j=i;j<=maxn;j+=i)
sgm[j]+=i;
for(int i=;i<=maxn;i++)
a[i].s=sgm[i],a[i].id=i;
sort(a+,a+maxn+,cmp1);
} int main()
{
//freopen("t1.in","r",stdin);
scanf("%d",&T);
Pre();
int x,y,z;
for(int t=;t<=T;t++)
{
scanf("%d%d%d",&Q[t].n,&Q[t].m,&Q[t].A);
Q[t].id=t;
}
sort(Q+,Q+T+,cmp2);
int k=;
for(int t=;t<=T;t++)
{
while(k<=maxn&&a[k].s<=Q[t].A){
int i=a[k].id;
for(int j=i;j<=maxn;j+=i)
update(j,sgm[i]*mu[j/i]%mod);
k++;}
if(Q[t].n>Q[t].m) swap(Q[t].n,Q[t].m);
int n=Q[t].n,m=Q[t].m;ll ans=;
for(int j=,la;j<=n;j=la+){
la=min(n/(n/j),m/(m/j));
(ans+=1ll*(n/j)*(m/j)%mod*(query(la)-query(j-))%mod)%=mod;
}Q[t].ans=(1ll*ans%mod+mod)%mod;
}
sort(Q+,Q+T+,cmp3);
for(int t=;t<=T;t++)
printf("%lld\n",Q[t].ans);
return ;
}

BZOJ 3529 [Sdoi2014]数表 (莫比乌斯反演+树状数组+离线)的更多相关文章

  1. BZOJ 3529: [Sdoi2014]数表 [莫比乌斯反演 树状数组]

    3529: [Sdoi2014]数表 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 1399  Solved: 694[Submit][Status] ...

  2. 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 ...

  3. BZOJ 3259 [Sdoi2014]数表 (莫比乌斯反演 + 树状数组)

    3529: [Sdoi2014]数表 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 2321  Solved: 1187[Submit][Status ...

  4. 【BZOJ3529】[Sdoi2014]数表 莫比乌斯反演+树状数组

    [BZOJ3529][Sdoi2014]数表 Description 有一张N×m的数表,其第i行第j列(1 < =i < =礼,1 < =j < =m)的数值为能同时整除i和 ...

  5. BZOJ3529: [Sdoi2014]数表(莫比乌斯反演 树状数组)

    题意 题目链接 Sol 首先不考虑\(a\)的限制 我们要求的是 \[\sum_{i = 1}^n \sum_{j = 1}^m \sigma(gcd(i, j))\] 用常规的套路可以化到这个形式 ...

  6. luogu3312 [SDOI2014]数表 (莫比乌斯反演+树状数组)

    link \(\sum_{i=1}^n\sum_{j=1}^m[s(\gcd(i,j))\le a]s(\gcd(i,j))\) \(=\sum_{p=1}^ns(p)[s(p)\le a]\sum_ ...

  7. bzoj 3529 数表 莫比乌斯反演+树状数组

    题目大意: 有一张N×m的数表,其第i行第j列(1 < =i < =礼,1 < =j < =m)的数值为能同时整除i和j的所有自然数之和.给定a,计算数表中不大于a的数之和. ...

  8. 【BZOJ3529】【莫比乌斯反演 + 树状数组】[Sdoi2014]数表

    Description 有一张N×m的数表,其第i行第j列(1 < =i < =礼,1 < =j < =m)的数值为 能同时整除i和j的所有自然数之和.给定a,计算数表中不大于 ...

  9. BZOJ_3529_[Sdoi2014]数表_莫比乌斯反演+树状数组

    Description 有一张 n×m 的数表,其第 i 行第 j 列(1 <= i <= n, 1 <= j <= m)的数值为 能同时整除 i 和 j 的所有自然数之和.给 ...

随机推荐

  1. 哪里获取ZBrush简体中文版?

    ZBrush®精简版(ZBrush简体中文版)ZBrushCore发布已经有一段日子了,相信不少人早已迫不及待地开始尝试了,不知道你们的体验如何?毋庸置疑的是,ZBrushCore专为刚接触3D并希望 ...

  2. [THUWC2017]在美妙的数学王国中畅游 LCT+泰勒展开+求导

    p.s. 复合函数求导时千万不能先带值,再求导. 一定要先将符合函数按照求导的规则展开,再带值. 设 $f(x)=g(h(x))$,则对 $f(x)$ 求导: $f'(x)=h'(x)g'(h(x)) ...

  3. pupload上传插件问题整理

    前些日子公司网站需要开发一个类似与百度文库上传文档的功能,实现文档的批量上传.展示以及继续上传的功能.开发完成后,通过在多版浏览器下的使用,发现了一系列问题,特总结于下,以免来者在这些问题上耗费太多时 ...

  4. POJ 1988 Cube Stacking( 带权并查集 )*

    POJ 1988 Cube Stacking( 带权并查集 ) 非常棒的一道题!借鉴"找回失去的"博客 链接:传送门 题意: P次查询,每次查询有两种: M x y 将包含x的集合 ...

  5. Django -聚合分组,FQ操作, cookie, session

    一. 聚合查询和分组 1. 聚合 aggregate(*args, **kwargs) 对一组数据进行统计分析, 通过对QuerySet进行计算, 返回一个聚合值得字典. arrgregate()中每 ...

  6. 旋转VR相机不头晕:一个反直觉的发现

    旋转VR相机不头晕:一个反直觉的发现 本文章由cartzhang编写,转载请注明出处. 所有权利保留. 文章链接:http://blog.csdn.net/cartzhang/article/deta ...

  7. C语言使用memcpy函数实现两个数间任意位置的复制操作

    c和c++使用的内存拷贝函数,memcpy函数的功能是从源src所指的内存地址的起始位置开始拷贝n个字节到目标dest所指的内存地址的起始位置中. 用法:void *memcpy(void *dest ...

  8. apche本地测试,无法访问此网站

  9. java.lang.RuntimeException: java.sql.SQLSyntaxErrorException: ORA-00911: 无效字符

    这种情况可能是因为在设置数据库的时候,没有配置数据库的方言,导致sql语句无法被识别. 例如在配置Jfinal的配置文件的时候 如果不配置数据库的方言,默认下它是MySQL的,当使用oracle数据库 ...

  10. bzoj5157: [Tjoi2014]上升子序列(树状数组LIS)

    5157: [Tjoi2014]上升子序列 题目:传送门 题解: 学一下nlogn的树状数组求最长上生子序列就ok(%爆大佬) 离散化之后,用一个数组记录一下,直接树状数组做 吐槽:妈耶...一开始不 ...