zoukankan      html  css  js  c++  java
  • 【map】【分解质因数】CDOJ1572 Espec1al Triple

    先把公比为1,即前项 中项 末项相同的统计出来。对每一类数C(n,3)即可。

    然后我们发现,因为a1*a3=(a2)^2,所以a1和a3进行质因子分解之后,每一个质因子的指数的奇偶性必然相同,否则无法满足乘积为完全平方数。

    然后sqrt(100000)以内的素数只有65个,我们对于每一个数,用unsigned long long存一个01串,代表前64个素因子的奇偶性,再单独用一个布尔存第65个。

    然后该数还有可能有一个大素因子(>sqrt(x)),单独存一下,这样用一个三元组唯一标示每一个数。

    a1和a3的三元组必然完全相同。

    于是对于这样一个三元组,开个map套vector记录下符合其的数的个数(不超过log个),然后就很容易统计了。

    复杂度其实很低,就是常数挺大。

    #include<cstdio>
    #include<bitset>
    #include<map>
    #include<iostream>
    #include<cmath>
    #include<vector>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    struct Point{
    	ull S;
    	int x;
    	int y;
    	Point (const ull &A,const int &X,const int &Y){
    		S=A;
    		x=X;
    		y=Y;
    	}
    	Point(){
    		
    	}
    };
    bool operator < (const Point &a,const Point &b){
    	if(a.S!=b.S){
    		return a.S<b.S;
    	}
    	if(a.x!=b.x){
    		return a.x<b.x;
    	}
    	return a.y<b.y;
    }
    map<Point,vector<int> >ma;
    ll ans;
    bool vis[100000];
    int pri[1000],pr;
    void shai(){
    	vis[1]=1;
    	for(int i=1;i*i<=100000;++i){
    		if(!vis[i]){
    			pri[pr++]=i;
    			for(int j=i*i;j*j<=100000;j+=i){
    				vis[j]=1;
    			}
    		}
    	}
    }
    int n,m,a[1000010];
    ll num[100010];
    int main(){
    //	freopen("e.in","r",stdin);
    	shai();
    	scanf("%d",&n);
    	for(int i=1;i<=n;++i){
    		scanf("%d",&a[i]);
    		++num[a[i]];
    	}
    	for(int i=1;i<=100000;++i){
    		ans+=(num[i]*(num[i]-1ll)*(num[i]-2ll))/6ll;
    	}
    	sort(a+1,a+n+1);
    	int last=1;
    	for(int i=1;i<=n;++i){
    		if(a[i]!=a[i-1]){
    			int x=a[i];
    			ull S=0;
    			for(int j=0;j<pr-1;++j){
    				int cnt=0;
    				while(x%pri[j]==0){
    					++cnt;
    					x/=pri[j];
    				}
    				if(cnt%2!=0){
    					S|=((ull)1<<j);
    				}
    			}
    			int y=0,z;
    			while(x%pri[pr-1]==0){
    				++y;
    				x/=pri[pr-1];
    			}
    			y%=2;
    			z=x;
    			vector<int> v=ma[Point(S,y,z)];
    			for(int j=0;j<v.size();++j){
    				ans+=num[a[i]]*num[v[j]]*num[(int)(sqrt((ll)a[i]*(ll)v[j])+0.5)];
    			}
    			ma[Point(S,y,z)].push_back(a[i]);
    			last=i;
    		}
    	}
    	cout<<ans<<endl;
    	return 0;
    }
  • 相关阅读:
    所写既所思
    OO总结
    OO第三单元作业总结
    OO第二单元作业总结
    OO第一单元作业总结
    oo第四单元与课程总结
    oo第三单元总结——jml
    oo第二单元博客总结
    面向对象设计与构造-第一单元作业总结
    个人总结-不说再见
  • 原文地址:https://www.cnblogs.com/autsky-jadek/p/6718367.html
Copyright © 2011-2022 走看看