CF980D Perfect Groups
题目链接:http://codeforces.com/contest/980/problem/D
题目大意:
对于 \(n\) 个数,考虑它的所有子串,每个个子串中的数字最少能分成 \(k\) 组,使得每一组中的所有数对之积都为完全平方数。对于每一个 \(k\) ,输出相应的子串数。
知识点: 算术基本定理
解题思路:
对完全平方数进行质因数分解,不难发现它的所有质因数的指数都为偶数。因此两个数之积若为完全平方数,则这两者的所有质因子的指数之和必为偶数。对此,我们只需要考虑每个数的指数为奇数的质因子(若指数为偶数对于积的质因数的奇偶性没有影响),若两个数的指数为奇数的质因子相同,则二者相乘即得完全平方数。
AC代码:
1 #include <bits/stdc++.h> 2 3 using namespace std; 4 const int maxn = 5000+5; 5 6 int ans[maxn],a[maxn]; 7 8 int trans(int x){ //将 x 转化成由其指数为奇数的质因子相乘而得到的数 9 if(x==0||x==1||x==-1) return x; 10 11 int ret=1; 12 if(x<0){ 13 ret=-1; 14 x=-x; 15 } 16 for(int i=2;i*i<=x;i++){ 17 if(x%i==0){ 18 int has=0; 19 while(x%i==0){ 20 has++; 21 x/=i; 22 } 23 if(has%2==1) 24 ret*=i; 25 } 26 } 27 return ret*x; 28 } 29 30 map<int,int>vis; 31 int ind[maxn]; 32 bool used[maxn]; 33 int main(){ 34 int n; 35 scanf("%d",&n); 36 int cnt=0; 37 for(int i=1;i<=n;i++){ 38 scanf("%d",&a[i]); 39 a[i]=trans(a[i]); 40 41 //以下是一个 O(n*n) 的暴力 42 int t=vis[a[i]]; 43 if(!t){ 44 cnt++; 45 vis[a[i]]=cnt; 46 ind[i]=cnt; 47 } 48 else 49 ind[i]=t; 50 } 51 52 for(int i=1;i<=n;i++){ 53 memset(used,false,sizeof(used)); 54 cnt=0; 55 for(int j=i;j<=n;j++){ 56 if(a[j]==0){ 57 if(cnt==0) ans[1]++; 58 else ans[cnt]++; 59 } 60 else{ 61 if(!used[ind[j]]){ 62 used[ind[j]]=true; 63 cnt++; 64 } 65 ans[cnt]++; 66 } 67 } 68 } 69 for(int i=1;i<=n;i++){ 70 if(i!=1) printf(" "); 71 printf("%d",ans[i]); 72 }printf("\n"); 73 74 return 0; 75 }
“这些年我一直提醒自己一件事情,千万不要自己感动自己。大部分人看似的努力,不过是愚蠢导致的。什么熬夜看书到天亮,连续几天只睡几小时,多久没放假了,如果这些东西也值得夸耀,那么富士康流水线上任何一个人都比你努力多了。人难免天生有自怜的情绪,唯有时刻保持清醒,才能看清真正的价值在哪里。”