zoukankan      html  css  js  c++  java
  • cf round480D Perfect Groups

    题意:给一个序列,对于每一个连续的区间,区间内的数至少分成几个组,使得每个组内的数任意2个相乘是一个完全平方数(包括0)。 输出每个组数的个数。

    $n leq 5000 , |a_i| leq 10^8$

    我们发现,对于一个数$x$,我们把$x$所有成对的相同质因子除去之后得到的数是$f(x)$

    那么分到同一个组的所有数的$f(x_i)$相同,0可以被分到任何集合

    明显我们可以$n^2$做这道题,枚举一个子序列的右端点,然后从右到左枚举左端点,顺便维护最小组数。

    对于加入一个数$x$,我们需要知道当前区间里面的数是否有和$x$相同的,如果有相同的,就加入那个集合,否则就新开一个集合

    所以对于每一个点,我们预处理下一个和它相同的数的位置

    当然0的情况不同,随便加到任意一个集合就可以了

    //Serene
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<cmath>
    #include<set>
    using namespace std;
    #define ll long long
    #define db double
    #define For(i,a,b) for(int i=(a);i<=(b);++i)
    #define Rep(i,a,b) for(int i=(a);i>=(b);--i)
    const int maxn=5000+7,M=120;
    ll n,a[maxn],nxt[maxn],ans[maxn];
    set<ll> prime;
    set<ll>::iterator it;
    
    char cc;ll ff;
    template<typename T>void read(T& aa) {
    	aa=0;ff=1; cc=getchar();
    	while(cc!='-'&&(cc<'0'||cc>'9')) cc=getchar();
    	if(cc=='-') ff=-1,cc=getchar();
    	while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
    	aa*=ff;
    }
    
    ll qp(ll x,ll k,ll mod) {
    	ll rs=1;
    	while(k) {
    		if(k&1) rs=rs*x%mod;
    		k>>=1; x=x*x%mod;
    	}
    	return rs;
    }
    
    ll gcd(ll x,ll y) {return y==0? x:gcd(y,x%y);}
    
    bool isprime(ll n) {
    	if(n==2||n==3||n==5||n==7) return 1;
    	if(n<2||(n%6!=1&&n%6!=5)) return 0;
    	ll m=n-1,t=0,x,y;
    	while((m&1)==0) t++,m>>=1;
    	For(qaq,1,20) {
    		x=rand()%(n-2)+2;
    		x=qp(x,m,n);
    		For(i,1,t) {
    			y=x*x%n;
    			if(y==1&&x!=1&&x!=n-1) return 0;
    			x=y;
    		}
    		if(x!=1) return 0;
    	}
    	return 1;
    }
    
    ll prho(ll n,ll m) {
    	ll x=rand()%(n-1)+1,y=0;
    	for(ll i=1,k=1,d;y!=x;++i) {
    		if(i==k) {y=x;k<<=1;}
    		x=(x*x+m)%n;
    		d=gcd((y-x+n)%n,n);
    		if(d>1&&d<n) return d;
    	}
    	return n;
    }
    
    void find(ll n,ll m) {
    	if(isprime(n)) {
    		it=prime.find(n);
    		if(it==prime.end()) prime.insert(n);
    		else prime.erase(it);
    		return;
    	}
    	ll p=n; while(p>=n) p=prho(n,m--);
    	find(p,M); find(n/p,M);
    }
    
    ll get_num(ll n) {
    //	cerr<<"get_num("<<n<<")
    ";
    	if(n==1||n==0) return n;
    	find(n,M);
    	ll rs=1;
    	while(!prime.empty()) {
    		it=prime.begin();
    		rs*=*it;
    		prime.erase(it);
    	}
    	return rs;
    }
    
    int main() {
    	read(n); ll x;
    	For(i,1,n) {
    //		cerr<<"get a["<<i<<"]:";
    		read(x);
    		a[i]=get_num(abs(x));
    		if(x<0) a[i]=-a[i];
    	}
    	For(i,1,n) {
    		nxt[i]=n+1;
    		For(j,i+1,n) if(a[j]==a[i]) {nxt[i]=j;break;}
    	}
    	int now;
    	For(i,1,n) {
    		now=0;
    		Rep(j,i,1) {
    			if(a[j]&&nxt[j]>i) ++now;
    			++ans[now];
    		}
    	}
    	ans[1]+=ans[0];
    	For(i,1,n) printf("%lld ",ans[i]);
    	printf("
    ");
    	return 0;
    }
    

      

  • 相关阅读:
    TP5.1 路由验证器验证返回json提示
    win10 docker ubuntu14.04 php 编译安装 php7.3.20
    ubuntu15.10 sources.list 修改
    秒杀系统设计
    class命名规范
    php实现阿里云签名类
    【小程序】应用的生命周期,页面的生命周期
    php.ini配置文件参数中文说明文档
    tp5.1 nginx配置
    phpstudycomposer thinkPHP5.1 使用
  • 原文地址:https://www.cnblogs.com/Serene-shixinyi/p/9095228.html
Copyright © 2011-2022 走看看