zoukankan      html  css  js  c++  java
  • 【CF980D】Perfect Groups(仔细一想是道水题)

    点此看题面

    • 给定一个长度为(n)的序列。
    • 定义一个序列的值为最少要划分多少组,使得每组的数两两乘积都是平方数。
    • 现在要对于每个(kin[1,n]),求出这个序列有多少值为(k)的子串。
    • (nle5000)

    解题思路

    重要的事情放前面:注意特殊处理(0)的情况,因为(0)可以贴到任意一组里面!

    然后考虑不为(0)的情况,我们先去掉(a_i)的全部平方因子,然后就发现两数乘积为平方数只可能是这两数相同。

    也就是只有相同的数才能并到一组,而既然要求最小组数,则相同的数必然并到一组,因此只要求有多少不同的数即可。

    直接暴枚所有子串就做完了。

    代码:(O(n^2))

    #include<bits/stdc++.h>
    #define Tp template<typename Ty>
    #define Ts template<typename Ty,typename... Ar>
    #define Reg register
    #define RI Reg int
    #define Con const
    #define CI Con int&
    #define I inline
    #define W while
    #define N 5000
    using namespace std;
    int n,a[N+5],dc,dv[N+5],s[N+5],vis[N+5];
    int main()
    {
    	RI i,j;for(scanf("%d",&n),i=1;i<=n;dv[i]=a[i],++i)
    		for(scanf("%d",a+i),j=2;j*j<=abs(a[i]);++j) W(!(a[i]%(j*j))) a[i]/=j*j;//除去所有平方因子
    	sort(dv+1,dv+n+1),dc=unique(dv+1,dv+n+1)-dv-1;//排序去重
    	for(i=1;i<=n;++i) a[i]=lower_bound(dv+1,dv+dc+1,a[i])-dv;//离散化
    	RI t;for(i=1;i<=n;++i) for(t=0,j=i;j<=n;++j)//暴枚子串
    		dv[a[j]]&&vis[a[j]]^i&&(vis[a[j]]=i,++t),++s[max(t,1)];//统计有多少不同的数(0除外),但注意全是0也得有一组
    	for(i=1;i<=n;++i) printf("%d%c",s[i]," 
    "[i==n]);return 0;//输出答案
    }
    
  • 相关阅读:
    getfacl语法2
    getfacl
    setfacl语法2
    setfacl语法
    特殊权限语法2
    特殊权限语法
    vim语法
    locate语法
    find语法
    dos语法
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/CF980D.html
Copyright © 2011-2022 走看看