bzoj3529:[Sdoi2014]数表
传送门
可以先不管\(a\)的限制
显然问题可以转化,对于一个数\(i*j\),能同时整除\(i\)并且整除\(j\)的数\(x\),也就是满足\(x|i\&\&y|j\),则\(x|gcd(i,j)\),也就是\(x\)为\(gcd(i,j)\)的约数,设\(g(n)\)为\(n\)的约数和,那么
\[
ans=\sum_{d=1}^{min(n,m)}\sum_{i=1}^{n}\sum_{j=1}^{m}[gcd(i,j)==d]g(d)\\
ans=\sum_{d=1}^{min(n,m)}g(d)\sum_{i=1}^{n}\sum_{j=1}^{m}[gcd(i,j)==d]\\
\]
然后设
\[
f(d)=\sum_{i=1}^{n}\sum_{j=1}^{m}[gcd(i,j)==d]\\
F(d)=\sum_{d|a}f(a)=\lfloor \frac{n}{d}\rfloor\lfloor \frac{m}{d}\rfloor\sum_{i=1}^{n}\sum_{j=1}^{m}[d|gcd(i,j)]\\
f(x)=\sum_{x|d}F(d)\mu(\frac{d}{x})=\sum_{x|d}\lfloor \frac{n}{d}\rfloor\lfloor \frac{m}{d}\rfloor\mu(\frac{d}{x})\\
\]
然后\(ans\)可以转化了
\[
ans=\sum_{d=1}^{min(n,m)}g(d)f(d)\\
ans=\sum_{d=1}^{min(n,m)}g(d)\sum_{d|y}\lfloor \frac{n}{y}\rfloor\lfloor \frac{m}{y}\rfloor\mu(\frac{y}{d})\\
ans=\sum_{d=1}^{min(n,m)}\lfloor \frac{n}{d}\rfloor\lfloor \frac{m}{d}\rfloor \sum_{d|y}g(d)\mu(\frac{y}{d})\\
\]
然后约数和可以线筛的时候处理出来
这个时候应该拾起那个没有考虑的\(a\)了
考虑离线,当\(g(d)<=a\)的时候会产生贡献,排序一下
然而数论分块是需要前缀和的,有什么快速维护前缀和并且支持单点修改的数据结构呢
树状数组是个不错的选择
代码:
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
void read(int &x) {
char ch; bool ok;
for(ok=0,ch=getchar(); !isdigit(ch); ch=getchar()) if(ch=='-') ok=1;
for(x=0; isdigit(ch); x=x*10+ch-'0',ch=getchar()); if(ok) x=-x;
}
#define rg register
#define lowbit(i) (i&(-i))
const int maxn=1e5+10,mod=(1<<31)-1;
int T,ans[maxn],mu[maxn],pri[maxn],tot,mx,s[maxn],f[maxn];bool vis[maxn];
struct o{int n,m,a,id;}a[maxn];
struct oo{int x,y;}g[maxn];
bool cmp(oo a,oo b){return a.x<b.x;}
bool Cmp(o a,o b){return a.a<b.a;}
void prepare(int x)
{
mu[1]=1,s[1]=1;
for(rg int i=2;i<=x;i++)
{
if(!vis[i])pri[++tot]=i,mu[i]=-1,s[i]=i+1;
for(rg int j=1;j<=tot&&pri[j]*i<=x;j++)
{
vis[pri[j]*i]=1;
if(!(i%pri[j])){s[i*pri[j]]=s[i]*s[pri[j]]-s[i/pri[j]]*pri[j];break;}
else s[i*pri[j]]=s[i]*s[pri[j]],mu[i*pri[j]]=-mu[i];
}
}
for(rg int i=1;i<=x;i++)g[i].x=s[i],g[i].y=i;
sort(g+1,g+x+1,cmp);
}
void add(int x,int y){for(rg int i=x;i<=mx;i+=lowbit(i))f[i]+=y;}
int get(int x){int ans=0;for(rg int i=x;i;i-=lowbit(i))ans+=f[i];return ans;}
int solve(int n,int m)
{
if(n>m)swap(n,m);int ans=0;
for(rg int i=1,j;i<=n;i=j+1)
{
j=min(n/(n/i),m/(m/i));
int t=(n/i)*(m/i)*(get(j)-get(i-1));
ans+=t;
}
return ans;
}
int main()
{
read(T);
for(rg int i=1;i<=T;i++)read(a[i].n),read(a[i].m),read(a[i].a),a[i].id=i,mx=max(mx,max(a[i].n,a[i].m));
prepare(mx);sort(a+1,a+T+1,Cmp);int now=1;
for(rg int i=1;i<=T;i++)
{
while(now<=mx&&g[now].x<=a[i].a)
{
for(rg int j=g[now].y;j<=mx;j+=g[now].y)
add(j,g[now].x*mu[j/g[now].y]);
now++;
}
ans[a[i].id]=solve(a[i].n,a[i].m);
}
for(rg int i=1;i<=T;i++)printf("%d\n",ans[i]&((1<<31)-1));
}
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- springmvc之RequestMapping结合@PathVariable使用
- springmvc之CookieValue注解
- springmvc之处理模型数据ModelAndView
- springmvc之异常处理ResponseStatusExceptionResolver
- Java矩阵快速幂实现
- 走近STL -- 你好,List
- 我能看懂的MakeFile(自命名,多文件,多目标)
- Posix信号量与cond条件变量,到底该选谁?
- 信号量--System V信号量 与 Posix信号量
- 文件空间映射mmap()函数(是什么,为什么,怎么用)
- C++下shm共享内存模块
- 基于TypeScript封装Axios笔记(九)
- springmvc之SessionAttributes注解所引发的异常
- 【tensorflow2.0】处理文本数据-imdb数据
- springmvc之异常处理DefaultHandlerExceptionResolver