【luogu CF1553F】Pairwise Modulo(树状数组)(根号分治)

Pairwise Modulo

题目链接:luogu CF1553F

题目大意

给你一个序列,对于每个前缀,要你求两两互相取模的结果的和。

思路

考虑新加入一个数增加的答案。
那就是加两个部分:
i=1n1an%ai
i=1n1ai%an

然后分别考虑。
不过有一个通用的化法就是 a%b=aabb
然后:

i=1n1ananaiai
i=1n1aiaianan

an(n1)i=1n1anaiai
i=1n1aii=1n1aianan

那就看怎么算两个的右边。
发现第二个是好搞的,直接枚举 aian 的值,然后查询 ankan(k+1)1 里面有多少个之前的数,用树状数组维护求即可。
然后 i=1nni=nlogn 所以复杂度为 O(nlog2n)

然后再看第一个,发现直接不好问,但是考虑从贡献的数的角度来看,那也看下取整的部分,它的多少倍就要让自己贡献多少次。
于是考虑每次放进去一个数 x,就把它倍数的所有位置都加上 x,然后询问的时候直接问 1y 的和即可,也是树状数组维护。
然后也是枚举倍数,也是树状数组,所以也是 nlog2n 的。


然后有一种根号分治的做法,但是复杂度会劣到 O(nnlogn),但也能过。
其实两种的想法差不多,这里只说第一个。
我们设定一个阀值 B,当数 B 的时候,我们暴力取模加入答案。
>B,这个时候模 n 的结果只有 nBlogn 种(不确定是不是这个不是很会分析),我们考虑枚举这些,然后找到对应的范围,也用树状数组查询数量。
然后当 B=nlogn 的时候,复杂度是 O(nnlogn)

代码

O(nlog2n)

#include<cmath> #include<cstdio> #include<iostream> #define ll long long using namespace std; const ll N = 3e5 + 2e5; const ll Lim = 3e5; ll n, a[N]; struct SZSZ { ll f[N]; void insert(ll x, ll y) { for (; x <= Lim; x += x & (-x)) f[x] += y; } ll query(ll x) { ll re = 0; for (; x; x -= x & (-x)) re += f[x]; return re; } ll ask(ll l, ll r) { return query(r) - query(l - 1); } }T, Ts; ll re; char c; ll read() { re = 0; c = getchar(); while (c < '0' || c > '9') c = getchar(); while (c >= '0' && c <= '9') { re = (re << 3) + (re << 1) + c - '0'; c = getchar(); } return re; } int main() { // freopen("read.txt", "r", stdin); // freopen("write.txt", "w", stdout); n = read(); for (ll i = 1; i <= n; i++) a[i] = read(); ll ans = 0, sum = 0; for (ll i = 1; i <= n; i++) { ans -= Ts.ask(1, a[i]); ans += 1ll * (i - 1) * a[i]; ll tmp = Lim / a[i]; for (int j = 1; j <= tmp; j++) { int L = j * a[i], R = min((j + 1) * a[i] - 1, Lim); ans -= 1ll * j * a[i] * T.ask(L, R); } ans += sum; T.insert(a[i], 1); sum += a[i]; for (ll j = a[i]; j <= Lim; j += a[i]) Ts.insert(j, a[i]); printf("%lld ", ans); } return 0; }

O(nnlogn)

#include<cmath> #include<cstdio> #include<iostream> #define ll long long using namespace std; const int N = 3e5 + 2e5; const int Lim = 3e5; int n, a[N], B; bool in[N]; struct SZSZ0 { int f[N]; inline void insert(int x, int y) { for (; x <= Lim; x += x & (-x)) f[x] += y; } inline int query(int x) { int re = 0; for (; x; x -= x & (-x)) re += f[x]; return re; } inline int ask(int l, int r) { return query(r) - query(l - 1); } }T; struct SZSZ { ll f[N]; inline void insert(int x, int y) { for (; x <= Lim; x += x & (-x)) f[x] += y; } inline ll query(int x) { ll re = 0; for (; x; x -= x & (-x)) re += f[x]; return re; } inline ll ask(int l, int r) { return query(r) - query(l - 1); } }Ts; int get_log(int x) { return x * (int)(log10(x) / log10(2)); } int re; char c; int read() { re = 0; c = getchar(); while (c < '0' || c > '9') c = getchar(); while (c >= '0' && c <= '9') { re = (re << 3) + (re << 1) + c - '0'; c = getchar(); } return re; } void write(ll x) { if (x > 9) write(x / 10); putchar(x % 10 + '0'); } int main() { // freopen("read.txt", "r", stdin); // freopen("write.txt", "w", stdout); n = read(); for (int i = 1; i <= n; i++) a[i] = read(); ll ans = 0, sum = 0; for (int i = 1; i <= n; i++) { B = max(1, (int)sqrt(get_log(a[i]))); int L = a[i] / 2 + 1, R = a[i], tmp = a[i] / B; for (int j = 1; j <= tmp; j++) { // int L = a[i] / (j + 1) + 1, R = a[i] / j; ans -= Ts.ask(L, R) * j; if (j != tmp) R = L - 1, L = a[i] / (j + 2) + 1; } for (int j = 1; j <= L - 1; j++) { if (!in[j]) continue; // ans -= a[i] - (a[i] - a[i] / j * j); ans -= a[i] / j * j; } ans += 1ll * (i - 1) * a[i]; tmp = Lim / a[i]; for (int j = 1; j <= tmp; j++) { int L = j * a[i], R = min(Lim, (j + 1) * a[i] - 1); ans -= 1ll * j * a[i] * T.ask(L, R); } ans += sum; T.insert(a[i], 1); Ts.insert(a[i], a[i]); sum += a[i]; in[a[i]] = 1; write(ans); putchar(' '); // printf("%lld ", ans); } return 0; } //根号分治

__EOF__

本文作者あおいSakura
本文链接https://www.cnblogs.com/Sakura-TJH/p/luogu_CF1553F.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   あおいSakura  阅读(26)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 张高兴的大模型开发实战:(一)使用 Selenium 进行网页爬虫
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
点击右上角即可分享
微信分享提示