Codeforces 980D Perfect Groups

题目大意

设有一个数组A和对A的一个操作f。那么f(A)返回一个最小的k,使得A能分成k组(每组元素不一定连续,但每个元素一定属于某一组),且每组里的任意两个元素的乘积是完全平方数。

现有一个长度为n的数组A,问有多少中情况,从A中取出一段连续的子序列B,使f(B)=k(k = 1...n)

解题思路

首先考虑操作f中的某一组中的某两个数a和b。因为\[ab = k^2(k \in Z)\]所以我们有\[a = \alpha^2t_1\]和\[b=\beta^2t_2\](α、β为整数且t1、t2不含平方因子)

由质因数分解易推出t1 = t2

所以那一组中的所有数去掉平方因子后都相等

又因为分的组数要最小,所以任意两个数若去掉平方因子后相等,那么他们一定在同一组中。

好了,在回头看如何实现题目要求。

首先第一步一定是去掉每个数的平方因子,记在a数组。之后,我们有一个巧妙的预处理。我们用f[i]保存在i前面第一个a[i] = a[f[i]]的位置。那么在一个区间中若a[i]不为0且f[i]小于这个区间的左端点,就一定不能与它之前的数并为一组,否则一定可以。然后看如何求答案。若我们对于每个k,都枚举区间左端点,再进行推进,那么效率就有些低了,有可能会TLE。所以我们换个角度思考。如果枚举左端点,然后一边按顺序扫左端点后面的点,一边记录到最后答案里,那么时间复杂度就只有O(n^2)。问题解决。

程序

#include<bits/stdc++.h>
using namespace std;
map<int, int> ct;//map能更快地完成初始化,也可以用O(n^2)的时间暴力初始化
int n, a[10010], f[10010], ans[10010], cnt;//a、f的意义如上面所说,ans保存最终答案
int l = 0, b[10010], p[10010];//p保存素数,b为临时数组
int main(){
    memset(b, 0, sizeof(b));
    memset(ans, 0, sizeof(ans));
    memset(p, 0, sizeof(p));
    memset(f, 0, sizeof(f));
    memset(a, 0, sizeof(a));
    n = 0;
    cnt = 0;
    l = 0;
    for(int i = 2; i < 10010; i++){
        if(b[i] == 0){
            l++; p[l] = i;
        } else continue;
        for(int j = i + i; j < 10010; j += i)
            if(b[j] == 0) b[j] = 1;
    }//以上完成素数筛选
    scanf("%d", &n);
    for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
    for(int i = 1; i <= n; i++)
        for(int j = 1; (j <= l) && ((p[j] * p[j]) <= abs(a[i])); j++){//小心有负数
            while(a[i] != 0 && a[i] % (p[j] * p[j]) == 0) a[i] /= (p[j] * p[j]);
            if(a[i] == 0 || a[i] == 1 || a[i] == -1) break;//已经结束,不如退出
        }
        //以上完成去除所有数的平方因子
    for(int i = 1; i <= n; i++){
        f[i] = ct[a[i]];
        ct[a[i]] = i;
    }//完成初始化
    for(int i = 1; i <= n; i++){
        cnt = 0;
        for(int j = i; j <= n; j++){
            if(a[j] && f[j] < i) cnt++; //注意0的情况
            ans[max(1, cnt)]++;
        }
    }//统计答案
    for(int i = 1; i <= n; i++)
        if(i == 1) printf("%d", ans[i]); else printf(" %d", ans[i]);
    printf("\n");
    return 0;
}

原文地址:https://www.cnblogs.com/chy-2003/p/9639490.html

时间: 2024-07-31 05:33:22

Codeforces 980D Perfect Groups的相关文章

CF 980D Perfect Groups(数论)

CF 980D Perfect Groups(数论) 一个数组a的子序列划分仅当这样是合法的:每个划分中的任意两个数乘积是完全平方数.定义a的权值为a的最小子序列划分个数.现在给出一个数组b,问权值为i的b的子串个数. 这题意真不是人类智慧能轻易描述的.据说此题在比赛场上读题30min,做题5min,做完还WA.果然是坑题. 如果有两个数a和b,a和b的乘积是完全平方数,那么如果a有因子x^2,那么x^2就可以去掉,使a变成a/x^2,结论依然成立.因此我们把所有数的质因子次数mod2,可以发现

Codeforces 948D Perfect Security(字典树)

题目链接:Perfect Security 题意:给出N个数代表密码,再给出N个数代表key.现在要将key组排序,使key组和密码组的亦或所形成的组字典序最小. 题解:要使密码组里面每个数都找到能使其亦或和最小的数可以将key建成一棵字典树(这里建树方式很关键,可以每个数都从2^31开始建树,这样可以使我们在遍历树查询更加方便).之后再遍历密码组每次在字典树里面找到一个能使它亦或和最小的数,再将这个数从字典树中删掉...  字典树太久不写,很多东西都忘记了! 1 #include<bits/s

CF980D Perfect Groups

思路: 注意到若A * B和B * C都是完全平方数,则A * C也是完全平方数,就不难解答了,要特判0的情况. 实现: 1 #include <bits/stdc++.h> 2 using namespace std; 3 const int MAXN = 5005; 4 int a[MAXN], par[MAXN], buf[MAXN]; 5 typedef long long ll; 6 void init(int n) 7 { 8 for (int i = 0; i < n; i

Codeforces Round #480 (Div. 2) C 贪心 D 数字、思维 E 树上倍增

Codeforces Round #480 (Div. 2) C. Posterized 题意: 给出 n 个数,都是区间 [0,255] 内的数,要你把 [0,255] 划分成多个长度 <=k 的不重叠的子区间.每个数必须包含在一个子区间内,且这个数的价值是这个子区间的左端点.要你输出这 n 数的价值,且这 n 个价值字典序要最小. tags: 首先很明显字典序最小,那对于第 i 个数 p[i] 定它的区间时,左端点肯定要尽可能小.所以我们直接枚举区间 [ p[i]-k+1, p[i] ] 定

屏姨讶们是h25vhc4y6ece5

说到这里,玄老的声音中明显多了几分悲怆的味道"他们都是好孩子,尽管他们未能真正毕业,但在学院的名册上,始终有着他们的名字.他们以学院的理想为理想,他们并不是没有毕业的实力,而是为了学院的理想战死了."-----------------------------------------------------------------------------周漪忍不住道:"有什么是学院不能帮你解决的?非要自己一个人去面对?难道你说出来我们会不帮你么?"可是--,聚能魂导炮

僦檬哨招瓤kdqg84x5hodqk1

台上,天煞斗罗黄津绪并没有催促双方进行下一场比赛,因为比赛台在刚才一战中被破坏的实在是太厉害了,马小桃的黑色凤凰火焰足足灼烧了一分多钟才消失.如果不进行修补,已经没法再继续比赛了.此时正由几位实力不俗的土系魂师快速修复着.自从进入史莱克学院之后,他们一直都在紧张的学习和修炼,哪有什么放松的时间.凌落宸的疑问则只是落在霍雨浩一个人身上,"极致之冰?"贝贝心中早有定计,低声道:"第一场我们赢了,我们就已经处于主动之中.我们现在最希望出现的.是第二场他们在冲动之下派出两名魂王,或者

滦谇淋坌招r6un44y803l1xog9y18

求收藏.求推荐票.求会员点击.刺入他额头的青色噬灵刻刀轻微震颤,奇异的是,那破入的创口并没有鲜血流出,反而是那噬灵刻刀竟然缓缓软化,化为青碧色的液体顺着那创口流入霍雨浩头部之中.霍雨浩呵呵一笑,道:"发现就发现呗,王冬,你现在是不是觉得特别虚弱,一点力气都用不出来啊?""战争最后虽然胜利了,但我们唐门暗器的作用也受到了极大的质疑.从那以后,各国开始大幅度削减对我们制作暗器的采购.而我们唐门赚钱虽然不少,但按照第一代门主的意思,大部分收入全都捐赠了出去.用来改善穷苦地区的平民生

Codeforces 388 D. Fox and Perfect Sets

$ >Codeforces \space 388 D. ?Fox?and?Perfect?Sets<$ 题目大意 : 定义一个完美的集合 \(S\) ,当且仅当 \(S\) 非负非空,且 \(\forall a, b \in S, a\text{ xor } b \in S\) ,求集合内最大元素不超过 \(n\) 的完美集合数量 \(1 \leq n \leq 10^9\) 解题思路 : 一个完美的集合等价于某个线性基能表示出的所有元素,所以问题转化为对能表示的最大元素 \(\leq n\)

Codeforces Round #460 (Div. 2) 919A. Supermarket 919B. Perfect Number 919C. Seat Arrangements

这场cf有点意思,hack场,C题等于1的特判hack很多人(我hack成功3个人,上分了,哈哈哈,咳咳...) D题好像是树形dp,E题好像是中国剩余定理,F题好像还是dp,具体的不清楚,最近dp的题目好多,一会滚去学dp. 写A,B,C的题解. A. Supermarket time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standard output