【刷题】BZOJ 3529 [Sdoi2014]数表
Description
有一张n×m的数表,其第i行第j列(1<=i<=n,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
Sample Output
20
148
HINT
1<=n,m<=10^5 , 1<=Q<=2×10^4
Solution
莫比乌斯反演,膜拜PoPoQQQ
先不管a的限制,我们直接求数表中所有数之和\(ans'\)
设\(F(i)\)为i的约数和,\(g(i)\)为在限制n和m范围内gcd为i的对数的个数,那么
\]
\(g(i)\)的反演已经是老套路了,直接得出\(g(i)=\sum_{i|d}\mu(\frac{d}{n})\lfloor \frac{n}{d} \rfloor \lfloor \frac{m}{d} \rfloor\)
继续推
\]
设\(T=ik\)
\]
前面部分整除分块,我们只要处理出后半部分的前缀和就行了
对于\(F(k)\)直接\(O(nlog_2n)\)暴力枚举约数和它的倍数
对于\(\mu\)这就不用说了吧。。。(看之前的文章)
好的,我们把改装之后的问题解决了,可是原问题呢?
回到真正的\(ans\),因为有a的限制,所以那些\(F(i)\)大于a的是不能加贡献的
那么我们把询问按a排序,然后用树状数组维护\(F(k)\mu(\lfloor \frac{T}{k} \rfloor)\)的前缀和,只有当前询问的a大于扫描到的\(F(i)\),才把\(F(i)\)能产生的贡献加入树状数组。这样就保证了不改加入的贡献不会被加入
#include<bits/stdc++.h>
#define ll long long
const int MAXT=20000+10,MAXN=100000+10,Mod=0x7fffffff;
int T,cnt,vis[MAXN],prime[MAXN],mu[MAXN],C[MAXN],ans[MAXT],limit;
struct question{
int n,m,a;
int id;
inline bool operator < (const question &A) const{
return a<A.a;
};
};
question Q[MAXT];
struct node{
int s;
int id;
inline bool operator < (const node &A) const{
return s<A.s;
};
};
node F[MAXN];
template<typename T> inline void read(T &x)
{
T data=0,w=1;
char ch=0;
while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
if(ch=='-')w=-1,ch=getchar();
while(ch>='0'&&ch<='9')data=((T)data<<3)+((T)data<<1)+(ch^'0'),ch=getchar();
x=data*w;
}
template<typename T> inline void write(T x,char c='\0')
{
if(x<0)putchar('-'),x=-x;
if(x>9)write(x/10);
putchar(x%10+'0');
if(c!='\0')putchar(c);
}
template<typename T> inline void chkmin(T &x,T y){x=(y<x?y:x);}
template<typename T> inline void chkmax(T &x,T y){x=(y>x?y:x);}
template<typename T> inline T min(T x,T y){return x<y?x:y;}
template<typename T> inline T max(T x,T y){return x>y?x:y;}
inline void init()
{
for(register int i=1;i<=limit;++i)
for(register int j=i;j<=limit;j+=i)F[j].s+=i;
for(register int i=1;i<=limit;++i)F[i].id=i;
std::sort(F+1,F+limit+1);
memset(vis,1,sizeof(vis));
vis[0]=vis[1]=0;
mu[1]=1;
for(register int i=2;i<=limit;++i)
{
if(vis[i])
{
prime[++cnt]=i;
mu[i]=-1;
}
for(register int j=1;j<=cnt&&i*prime[j]<=limit;++j)
{
vis[i*prime[j]]=0;
if(i%prime[j])mu[i*prime[j]]=-mu[i];
else break;
}
}
}
inline int lowbit(int x)
{
return x&(-x);
}
inline int sum(int x)
{
int res=0;
while(x)
{
res+=C[x];
x-=lowbit(x);
}
return res;
}
inline void add(int x,int k)
{
while(x<=limit)
{
C[x]+=k;
x+=lowbit(x);
}
}
inline int solve(int n,int m)
{
int res=0;
for(register int i=1;;)
{
if(i>min(n,m))break;
int j=min(n/(n/i),m/(m/i));
res+=(n/i)*(m/i)*(sum(j)-sum(i-1));
i=j+1;
}
return res&Mod;
}
int main()
{
read(T);
for(register int i=1;i<=T;++i)
{
read(Q[i].n);read(Q[i].m);read(Q[i].a);
Q[i].id=i;
chkmax(limit,min(Q[i].n,Q[i].m));
}
init();
std::sort(Q+1,Q+T+1);
for(register int i=1,j=1;i<=T;++i)
{
while(j<=limit&&F[j].s<=Q[i].a)
{
for(register int p=F[j].id,k=1;p<=limit;p+=F[j].id,++k)add(p,F[j].s*mu[k]);
++j;
}
ans[Q[i].id]=solve(Q[i].n,Q[i].m);
}
for(register int i=1;i<=T;++i)write(ans[i],'\n');
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]数表
题链: http://www.lydsy.com/JudgeOnline/problem.php?id=3529 题解: 莫比乌斯反演. 按题目的意思,令$f(i)$表示i的所有约数的和,就是要求: ...
- BZOJ 3529 [Sdoi2014]数表 (莫比乌斯反演+树状数组+离线)
题目大意:有一张$n*m$的数表,第$i$行第$j$列的数是同时能整除$i,j$的所有数之和,求数表内所有不大于A的数之和 先是看错题了...接着看对题了发现不会做了...刚了大半个下午无果 看了Po ...
- bzoj 3529 [Sdoi2014]数表(莫比乌斯反演+BIT)
Description 有一张N×m的数表,其第i行第j列(1 < =i < =礼,1 < =j < =m)的数值为能同时整除i和j的所有自然数之和.给定a,计算数表中不大于a ...
- 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次 ...
随机推荐
- 2018Java年底总结
一年又过去了,这是我的第二年的JAVA开发,总感觉有很多想说的,可惜语言组织能力着实一般,以下列举一些今年的总结. 1.首先告诫一下新入行或者新入职经验不多的小伙伴,写sql的时候根据业务能单表就单表 ...
- 2015第六届蓝桥杯C/C++ B组
奖券数目:枚举 有些人很迷信数字,比如带“4”的数字,认为和“死”谐音,就觉得不吉利.虽然这些说法纯属无稽之谈,但有时还要迎合大众的需求.某抽奖活动的奖券号码是5位数(10000-99999),要求其 ...
- js备忘录3
JavaScript也有类型转换 js中的获取指定位数的方法 +和-的转换方向不同 在JavaScript中首先给变量赋值数字,然后再给变量赋值字符串是合法的 这点和Java有些区别 在函数体内声明变 ...
- The serializable class XXX does not declare a static final serialVersionUID field of type long的警告
原文: http://blog.csdn.net/ultrakang/article/details/41820543
- “Hello World!”团队第七周召开的第六次会议
博客内容: 一.会议时间 二.会议地点 三.会议成员 四.会议内容 五.todo list 六.会议照片 七.燃尽图 八 .功能说明书 一.会议时间 2017年12月6日 11:20-12:00 二 ...
- c# 写文件注意问题及用例展示
以txt写string举例,正确代码如下: private void xie() { FileStream fs = new FileStream("1.txt", FileMod ...
- spring冲刺第八天
昨天使人物成功的在地图上运动,并设计炸弹爆炸效果. 今天使炸弹可以炸死人物并可以炸没砖块,并试着将小怪加入地图. 遇到的问题:现在还没有将小怪加入地图,各个模块的整合是比较麻烦的,我还要在这方面下点功 ...
- DataTime日期格式化
C# DateTime日期格式化 在C#中DateTime是一个包含日期.时间的类型,此类型通过ToString()转换为字符串时,可根据传入给Tostring()的参数转换为多种字符串格式. 目录 ...
- 28_数据库_第28天(数据库、表及表数据、SQL语句)_讲义
今日内容介绍 1.MySQL数据库 2.SQL语句 01数据库概念 A: 什么是数据库 数据库就是存储数据的仓库,其本质是一个文件系统,数据按照特定的格式将数据存储起来, 用户可以对数据库中的数据进行 ...
- 打开ubuntu终端的两个方法【最快速】
两种快捷方法: 1. ctrl+alt+T. 2. 桌面右击,再点击终端.