题目大意

  有一个长度为 \(n\) 的序列。

  有 \(m\) 次修改,每次给你 \(x,y\),令 \(\forall 1\leq i\leq \lfloor\frac{n}{x}\rfloor,a_{ix}=a_{ix}+iy\)

  还有 \(q\) 次询问,每次给你 \(x\),求 \(\sum_{i=1}^{\lfloor\frac{n}{x}\rfloor}ia_{ix}\)

  对 \(998244353\) 取模。

  \(n\leq {10}^9,m,q\leq 200000\),记 \(z\) 为所有 \(x\) 的 \(\operatorname{lcm}\),那么 \(z\) 的质因子个数 \(w\) 不超过 \(10\)

题解

  首先你要会 \(O(n\log\log n)\) 求高维前缀和&后缀和,这样就可以拿到 \(65\) 分。

  容易发现,所有 \(z\) 的不超过 \(n\) 的因子个数 \(s\leq 200000\)。

  因为所有修改&询问的数都是 \(z\) 的因子,所以可以把那些不是 \(z\) 的因子的位置的贡献放在那个数和 \(z\) 的 \(\gcd\) 处统计。

  具体来说,我们在求高维前缀和的时候只求 \(z\) 的不超过 \(n\) 的因子的答案,求完之后把每个位置 \(x\) 的值乘上一个系数 \(f(\frac{n}{x})\) 。

\[f(n)=\sum_{i=1}^ni^2[\gcd(i,z)=1]
\]

  \(f\) 可以筛出来。

  高维后缀和也可以用类似的方法做。

  然后就能得到答案了。

  时间复杂度:\(O(w(s+\sqrt{n}))\)

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<ctime>
#include<utility>
#include<functional>
#include<cmath>
#include<tr1/unordered_map>
//using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef std::pair<int,int> pii;
typedef std::pair<ll,ll> pll;
void open(const char *s){
#ifndef ONLINE_JUDGE
char str[100];sprintf(str,"%s.in",s);freopen(str,"r",stdin);sprintf(str,"%s.out",s);freopen(str,"w",stdout);
#endif
}
int rd(){int s=0,c,b=0;while(((c=getchar())<'0'||c>'9')&&c!='-');if(c=='-'){c=getchar();b=1;}do{s=s*10+c-'0';}while((c=getchar())>='0'&&c<='9');return b?-s:s;}
void put(int x){if(!x){putchar('0');return;}static int c[20];int t=0;while(x){c[++t]=x%10;x/=10;}while(t)putchar(c[t--]+'0');}
int upmin(int &a,int b){if(b<a){a=b;return 1;}return 0;}
int upmax(int &a,int b){if(b>a){a=b;return 1;}return 0;}
const ll p=998244353;
ll fp(ll a,ll b)
{
ll s=1;
for(;b;b>>=1,a=a*a%p)
if(b&1)
s=s*a%p;
return s;
}
const ll inv6=fp(6,p-2);
std::tr1::unordered_map<int,int> s;
//int s[10000010];
int c[100010];
int cnt;
int a[200010];
int tot;
int ax[200010],ay[200010],bx[200010];
int n,m,q;
void dfs(int x,int y,int b)
{
if(b)
a[++tot]=x;
if((ll)x*c[y]<=n)
dfs(x*c[y],y,1);
if(y<cnt)
dfs(x,y+1,0);
}
ll f1[100010],f2[100010];
ll sum(ll x)
{
return x*(x+1)%p*(2*x+1)%p*inv6%p;
}
void sieve()
{
int m=100000;
int mx=n/(m+1);
for(int i=1;i<=m;i++)
f1[i]=sum(i);
for(int i=1;i<=mx;i++)
f2[i]=sum(n/i);
for(int i=1;i<=cnt;i++)
{
ll x=(ll)c[i]*c[i]%p;
int n1=mx/c[i];
for(int j=1;j<=n1;j++)
f2[j]=(f2[j]-x*f2[j*c[i]])%p;
for(int j=n1+1;j<=mx;j++)
f2[j]=(f2[j]-x*f1[n/((ll)j*c[i])])%p;
for(int j=m;j>=1;j--)
f1[j]=(f1[j]-x*f1[j/c[i]])%p;
}
}
ll query(int x)
{
return x<=100000?f1[x]:f2[n/x];
}
int main()
{
open("loj561");
scanf("%d%d%d",&n,&m,&q);
for(int i=1;i<=m;i++)
{
scanf("%d%d",&ax[i],&ay[i]);
s[ax[i]]=(s[ax[i]]+ay[i])%p;
int x=ax[i];
for(int j=1;j<=cnt;j++)
while(x%c[j]==0)
x/=c[j];
for(int j=2;j*j<=x;j++)
if(x%j==0)
{
c[++cnt]=j;
while(x%j==0)
x/=j;
}
if(x!=1)
c[++cnt]=x;
}
for(int i=1;i<=q;i++)
{
scanf("%d",&bx[i]);
int x=bx[i];
for(int j=1;j<=cnt;j++)
while(x%c[j]==0)
x/=c[j];
for(int j=2;j*j<=x;j++)
if(x%j==0)
{
c[++cnt]=j;
while(x%j==0)
x/=j;
}
if(x!=1)
c[++cnt]=x;
}
std::sort(c+1,c+cnt+1);
dfs(1,1,1);
std::sort(a+1,a+tot+1);
sieve();
for(int i=1;i<=cnt;i++)
for(int j=1;j<=tot;j++)
if(a[j]%c[i]==0)
s[a[j]]=(s[a[j]]+(ll)s[a[j]/c[i]]*c[i])%p;
for(int i=1;i<=tot;i++)
s[a[i]]=s[a[i]]*query(n/a[i])%p;
for(int i=1;i<=cnt;i++)
for(int j=tot;j>=1;j--)
if(a[j]%c[i]==0)
s[a[j]/c[i]]=(s[a[j]/c[i]]+(ll)s[a[j]]*c[i])%p;
for(int i=1;i<=q;i++)
printf("%lld\n",(s[bx[i]]+p)%p);
return 0;
}

【LR9】【LOJ561】CommonAnts 的调和数 数论 筛法的更多相关文章

  1. 「LibreOJ Round #9」CommonAnts 的调和数

    题解: 对于subtask3:可以把相同的归在一起就是$nlogn$的了 对于subtask4: 可以使用高维前缀和的技术,具体的就是把每个质因数看作一维空间 那么时间复杂度是$\sum \limit ...

  2. XDU 1022 (数论筛法+前缀和)

    解法一:数论筛法+前缀和 //其实题目中f[n]的值可理解为存在多少个整数对使a*b<=n #include<cstdio> #define N 1007 #define maxn ...

  3. 数论 - 筛法暴力打表 --- hdu : 12876 Quite Good Numbers

    Quite Good Numbers Time Limit: 1000ms, Special Time Limit:2500ms, Memory Limit:65536KB Total submit ...

  4. ACM主要算法

    ACM主要算法ACM主要算法介绍 初期篇 一.基本算法(1)枚举(poj1753, poj2965)(2)贪心(poj1328, poj2109, poj2586)(3)递归和分治法(4)递推(5)构 ...

  5. ACM常用算法

    数据结构 栈,队列,链表 哈希表,哈希数组 堆,优先队列 双端队列 可并堆 左偏堆 二叉查找树 Treap 伸展树 并查集 集合计数问题 二分图的识别 平衡二叉树 二叉排序树 线段树 一维线段树 二维 ...

  6. ACM需要掌握算法

    数据结构 栈,队列,链表 哈希表,哈希数组 堆,优先队列 双端队列 可并堆 左偏堆 二叉查找树 Treap 伸展树 并查集 集合计数问题 二分图的识别 平衡二叉树 二叉排序树 线段树 一维线段树 二维 ...

  7. ACM用到的算法。先做个笔记,记一下

    ACM 所有算法 数据结构 栈,队列,链表 哈希表,哈希数组 堆,优先队列 双端队列 可并堆 左偏堆 二叉查找树 Treap 伸展树 并查集 集合计数问题 二分图的识别 平衡二叉树 二叉排序树 线段树 ...

  8. ACM算法目录

    数据结构 栈,队列,链表 •哈希表,哈希数组 •堆,优先队列 双端队列 可并堆 左偏堆 •二叉查找树 Treap 伸展树 •并查集 集合计数问题 二分图的识别 •平衡二叉树 •二叉排序树 •线段树 一 ...

  9. ACM技能表

    看看就好了(滑稽) 数据结构 栈 栈 单调栈 队列 一般队列 优先队列/单调队列 循环队列 双端队列 链表 一般链表 循环链表 双向链表 块状链表 十字链表 邻接表/邻接矩阵 邻接表 邻接多重表 Ha ...

随机推荐

  1. 《Pro Asp.net core mvc 2》bower问题

    在阅读<Pro Asp.net core mvc 2>中有使用bower管理包,可能是由于vs2017或者bootstrap什么地方改变了,按照步骤进行操作,完全没有对应的样式出现.开始以 ...

  2. AEAI CRM V1.6.0 升级说明,开源客户关系管理系统

    1 升级说明 AEAI CRM v1.6.0版是AEAI CRM v1.5.2版客户关系管理系统的升级版本,本次版本是基于AEAI DP v3.8.0_20170228进行打包部署的,升级内容主要是针 ...

  3. iOS ----------将照片保存到相册

    在使用前  请导入photos.framework 然后导入 #import <Photos/PHPhotoLibrary.h> #import <Photos/PHAssetCha ...

  4. python 生成图形验证码

    文章链接:https://mp.weixin.qq.com/s/LYUBRNallHcjnhJb1R3ZBg 日常在网站使用过程中经常遇到图形验证,今天准备自己做个图形验证码,这算是个简单的功能,也适 ...

  5. 操作DataTable数据,修改某列的值

    DataTable table : DataRow row=table.Rows[i];//DataTable的第i行 row.BeginEdit();//开始编辑行 row["column ...

  6. Centos6系列Bond配置方法

    在Windows Server平台因业务需求经常会用到NIC双网卡绑定,同样Linux平台下用于网络负载均衡及网络冗余会用到bond模式. Bond模式:0-6,即7种模式. 模式一:mod=0 ,即 ...

  7. Linux 文件权限管理

    1.文件权限的概述 在Linux系统下,使用权限来保护资源的安全将是一种不错的选择.系统中每个文件的权限都有可读(r).可写(w)和可执行(x)这三种权限,它们分别对应权限数值4.2 和1.系统为每个 ...

  8. php+qrcode类+生成二维码方法

    //生成二维码 public function qrcode() { $data = input(); if(!$data['param']){ return json(['code ' => ...

  9. (十)Modifying Your Data

    Elasticsearch provides data manipulation and search capabilities in near real time. By default, you ...

  10. 压力测试Apache

    在做类似商城秒杀系统的同事都知道要在支持高并发,高可用的环境下进行多次的压力测试来防止自己的项目结构被高额的点击量击穿,导致商品超卖等损失 介绍一款简单的软件 xampp xam里带了Apache服务 ...