题目大意

  有一个长度为 \(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. 2019-02-18 扩展Python控制台实现中文反馈信息之二-正则替换

    "中文编程"知乎专栏原文地址 续前文扩展Python控制台实现中文反馈信息, 实现了如下效果: >>> 学 Traceback (most recent call ...

  2. SAP freelancer夫妻并不难!你也可以!

    SAP freelancer夫妻并不难!你也可以! 在笔者看来,如果能有每月超过10万的家庭收入,要是去上海滩购买单价在八万以上的房子,应该是可以轻松应对,想买就可以买,根本不用眨眼睛,不用一丁点儿的 ...

  3. vue实现表计监测界面

    已经好几个月没有更新博客了,因为最近太忙,忙得连写博客的时间都没有.上班赶项目开启996模式,下班要去练车考驾照,一边还在赶书稿,一边还接了私活.不由得感叹:年纪大了,再也经不起那么折腾..... 每 ...

  4. Android 修改包名,导致安装错误

    一.app运行安装时出错 [安装时出错]: [百度翻译] 安装失败的消息未能敲定会议:install_failed_invalid_apk:/数据/应用程序/ vmdl292154713.tmp/9_ ...

  5. SpringBoot 配置 跨域支持

    跨域资源共享(CORS,请求协议,请求地址,请求端口三者必须相同才是同一服务器,否则都要进行跨域操作)标准新增了一组 HTTP 首部字段,允许服务器声明哪些源站有权限访问哪些资源.另外,规范要求,对那 ...

  6. MS SQL自定义函数判断是否正整数

    可以写一个函数: 主要是使用正则来判断.另外输入字符是空的话,使用"-"来替换. CREATE FUNCTION [dbo].[svf_NonNegativeInteger] ( ...

  7. linux缺页异常处理--内核空间

    缺页异常被触发通常有两种情况-- 程序设计的不当导致访问了非法的地址 访问的地址是合法的,但是该地址还未分配物理页框. 下面解释一下第二种情况,这是虚拟内存管理的一个特性.尽管每个进程独立拥有3GB的 ...

  8. iOS 开发 nonatomic 和 atomic

    nonatomic : 非原子属性 atomic    : 原子属性  如果不写关键字 那么默认就是 原子属性 - 多线程写入属性时,保证同一时间只有一个线程能够执行写入操作 - 单(线程)写多(线程 ...

  9. JavaScript -- 原型:prototype的使用

    JavaScript -- 原型:prototype的使用 在 JavaScript 中,prototype 是函数的一个属性,同时也是由构造函数创建的对象的一个属性. 函数的原型为对象. 它主要在函 ...

  10. 算法"新"名词

    这个“新”是对于自己而言. 最近几天接触到很多新的名词,如: 回溯法(backtracking):以前知道,但很少用 动态规划(dynamic programming):序列型.矩阵型.区间型.背包等 ...