首页 > 其他分享 >[CF980D] Perfect Groups 题解

[CF980D] Perfect Groups 题解

时间:2023-12-13 23:02:08浏览次数:38  
标签:Perfect Groups int 题解 CF980D rk

[CF980D] Perfect Groups 题解

思路

第一个观察就很难观察到:

\[ab = x^2, bc = y^2\Longrightarrow \exist z, ac = z^2(a, b, c \ne 0) \]

证明:

两个条件式相乘得到:

\[ab^2c = x^2y^2\\ ac = \dfrac{x^2 y^2}{b^2}(b\ne 0)\\ \because b | x^2, b | y^2\\ \therefore b^2| x^2y^2 \]

而由于算术基本定理,右式的分子每一个指数都是偶数,分母每一个都是偶数,相减所得到的每个指数也都是偶数,所以是完全平方数。

所以发现这个性质有传递性,可以考虑用并查集把 \(n\) 个数划分为若干个等价类,区间查询就是这个区间里面有多少个等价类。

注意到证明没有涵盖 0 的情况,事实上,0 乘以任何数都是完全平方数,所以如果一个区间里面有 0,无视它即可。

// Problem: Perfect Groups
// Contest: Luogu
// Author: Moyou
// Copyright (c) 2023 Moyou All rights reserved.
// Date: 2023-12-13 22:29:19

#include <iostream>
#include <cmath>
using namespace std;
typedef long long ll;
const int N = 2e5 + 10;

int n, a[N];
struct DSU {
    int fa[N], rk[N], top;
    DSU (int n) {
        for(int i = 1; i <= n; i ++)
            fa[i] = i, rk[i] = 1;
    }
    int find(int x) {return fa[x] == x ? x : fa[x] = find(fa[x]); }
    void merge(int a, int b) {
        int x = find(a), y = find(b);
        if(x == y) return ;
        if(rk[x] > rk[y]) swap(x, y);
        fa[x] = y, rk[y] += (rk[x] == rk[y]);
    }
    int count(int n) {
        int cnt = 0;
        for(int i = 1; i <= n; i ++)
            if(fa[i] == i) cnt ++;
        return cnt;
    }
    bool same(int a, int b) {return find(a) == find(b); };
};
bool check(ll x) {
    ll sq = sqrt(x);
    return sq * sq == x;
}
bool st[N];
ll ans[N];
signed main() {
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    cin >> n;
    for(int i = 1; i <= n; i ++) cin >> a[i];
    DSU dsu(n);
    for(int i = 1; i <= n; i ++) {
        for(int j = i + 1; j <= n; j ++)
            if(a[i] && a[j] && check(1ll * a[i] * a[j]))
                dsu.merge(i, j);
    }
    for(int i = 1, cnt; i <= n; i ++) {
        cnt = 0;
        for(int j = i; j <= n; j ++) {
            if(a[j] && st[dsu.find(j)] == 0) cnt ++, st[dsu.find(j)] = 1; // ignore 0
            ans[max(1, cnt)] ++;
        }
        for(int i = 1, cnt; i <= n; i ++) st[i] = 0;
    }
    for(int i = 1; i <= n; i ++)
        cout << ans[i] << ' ';

    return 0;
}

标签:Perfect,Groups,int,题解,CF980D,rk
From: https://www.cnblogs.com/MoyouSayuki/p/17900134.html

相关文章

  • P1004 [NOIP2000 提高组] 方格取数 题解
    P1004[NOIP2000提高组]方格取数题解题目链接P1004[NOIP2000提高组]方格取数简要思路注意一下输入可以简化为while(std::cin>>x>>y>>val&&x){ //***}运用DP的思想。用一个四维的\(DP\)数组\(dp[i][j][k][l]\)来同时记录两条路径分别走到\((i,j)\)和\((k,......
  • P4463 [集训队互测 2012] calc 题解
    Description一个序列\(a_1,a_2,\dots,a_n\)是合法的,当且仅当:\(a_1,a_2,\dots,a_n\)都是\([1,k]\)中的整数。\(a_1,a_2,\dots,a_n\)互不相等。一个序列的值定义为它里面所有数的乘积,即\(a_1\timesa_2\times\dots\timesa_n\)。求所有不同合法序列的值的和对\(p\)......
  • CF213E Two Permutation 题解
    CF213ETwoPermutations题解题意:给出两个排列$a,b$,长度分别为\(n,m\),你需要计算有多少个$x$,使得\(a_1+x,a_2+x,...a_n+x\)是\(b\)的子序列。\(n\leqm\leq2\times10^5\)分析:一个很自然的思路是直接枚举\(x\),然后只保留\(b\)中值域在\([x+1,x+n]\)......
  • 记一次 Zabbix agent is not available 问题解决
    好久没折腾zabbix,最近遇到一个奇葩的问题,忽然有一台服务器报警“Zabbixagentisnotavailable(ornodatafor30m)”,但是查看监控数据都有,而且在不断的更新开始分析问题、解决问题:1、先检查了一遍配置,都没问题2、检查了一遍server端和agent端的日志,也没有相应的错......
  • CF1500F Cupboards Jumps 题解
    题目链接点击打开链接题目解法感觉是一个融合了许多技巧的题,很巧妙题目要求\(\max(h_i,h_{i+1},h_{i+2})-\min(h_i,h_{i+1},h_{i+2})=w_i\),这可以转化成另一个只和两项有关的形式为:\(\max(|h_i-h_{i+1}|,|h_i-h_{i+2}|,|h_{i+1}-h_{i+2}|)=w_i\)令\(d_i=h_{i+1}-h_i\),所以......
  • springboot-micrometer潜在oom问题解决办法
    在服务中起一个监听Prometheus拉取的线程,在拉取完成之后清理调meterMap中内容比较多的tag,我这边是清理调gateway.requests.代码如下:@ComponentpublicclassPrometheusMeterRegistryFactory{@ResourceprivatePrometheusMeterRegistryprometheusMeterRegistry;......
  • CTFpwnAD世界pwnstack题解及栈溢出两种解法
    问题的出现这题我刚看到时差点没笑出来,但是尝试了一次之后我就笑不出来了。这题给了back_door后门函数,但是如果直接覆盖返回到后门函数起始位置会出现栈溢出问题。到这一步都没有出现问题,而继续ni的话就会卡住。基本上这里看到xmm0就是栈对其问题了。出现问题原因很简单,linux系统一......
  • 【洛谷 P1271】【深基9.例1】选举学生会 题解(计数排序)
    【深基9.例1】选举学生会题目描述学校正在选举学生会成员,有名候选人,每名候选人编号分别从1到,现在收集到了张选票,每张选票都写了一个候选人编号。现在想把这些堆积如山的选票按照投票数字从小到大排序。输入格式输入和以及个选票上的数字。输出格式求出排序后的选票编......
  • CTFpwnAD世界dice_game题解wp
    惯例checksec一下看看main首先seed函数用时间生成一个随机数,这个随机数做为srand函数的参数让srand函数生成一个种子。(这个种子会影响后面的rand函数生成结果,并且同样的种子会使rand函数生成同样的随机数,就是所谓的伪随机)以及看到这里会有连续五十轮游戏。sub_A20这里就是每一轮......
  • [ARC106F] Figures 题解
    题目链接点击打开链接题目解法这么神仙的推式子题看到生成树计数,第一反应是\(prufer\)序列考虑在\(prufer\)序列上搞这个东西可以得到\(ans=\sum\limits_{\sum\limits_{i=1}^nd_i=n-2}\binom{n-2}{d_1,d_2,...,d_n}\times\proda_i^{\underline{d_i+1}}\)考虑拆式子......