• Luogu P5856 【「SWTR-03」Game】


    Description

    传送门


    Solution

    读完题面之后我们首先可以想到要进行质因数分解。

    因为每次只能除以(prime^z)也就是说每次我们只能消除某一个质因子多出来的部分,所以对于每个质因子可以分开考虑。

    消去某个质因子多出来的部分只需要把这个质因子所有出现过的在每个数中的次数都记录下来,然后将一些数除以(prime^z)就相当于是从这些数中任意选取一些统一减去(z)

    那么这些数减到什么时候合法呢?因为最后所有这(n)个数都必须相等,所以每个质因子在每个数中的次数最多是所有这(n)个数的(gcd)中该质因子出现的次数。

    所以现在问题发生了转换,变成有一些数开始时从大到小递增,这些数只能是([1,20])中的数,要进行尽可能少的操作将所有数变成一样的且次数小于该质因子在(gcd)中出现的次数。

    接着可以发现,对于不同的质因子减数的效果是一样的,所以我们可以预处理出不同次数的最少次数,即用(dp[s])表示状态为(s)时最少操作次数。

    因为不一定要消到所有的质因子次数都为(0),所以预处理(gcd)中每个质因子出现的次数,这样只需要枚举最后每个质因数最后的次数的可行范围,即将(s)右移即可求出答案。


    Code

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    using namespace std;
    int n,a[724000][21],p[1000050],cnt,prime[1000050],ans,maxx,x[100050],anstmp,dp[2000050],gcdd,t[724000];
    int gcd(int a,int b){return b==0?a:gcd(b,a%b);}
    void xxs()
    {
    	p[0]=p[1]=1;
    	for(int i=2;i<=1000000;i++)
    	{
    		if(!p[i])prime[++cnt]=i;
    		for(int j=1;j<=cnt && prime[j]*i<=1000000;j++)
    		{
    			p[prime[j]*i]=1;
    			if(i%prime[j]==0)break;
    		}
    	}
    }
    void make(int x)
    {
    	for(int i=1;i<=cnt && prime[i]<=x;i++)
    	{
    		int tmp=0;
    		while(x%prime[i]==0)x/=prime[i],tmp++;
    		if(tmp>0)a[i][tmp]=1;
    	}
    }
    void print(int x)
    {
    	for(int i=20;i>=1;i--)
    		if((1<<(i-1)&x)==1<<(i-1))cout<<1;
    		else cout<<0;
    	cout<<endl;
    }
    int main()
    {
    	xxs();
    	scanf("%d",&n);
    	scanf("%d",&x[1]);
    	maxx=gcdd=x[1];
    	for(int i=2;i<=n;i++)scanf("%d",&x[i]),maxx=max(maxx,x[i]),gcdd=gcd(gcdd,x[i]);
    	for(int i=1;i<=cnt && prime[i]<=gcdd;i++)
    	{
    		int tmp=0;
    		while(gcdd%prime[i]==0)gcdd/=prime[i],tmp++;
    		if(tmp>0)t[i]=tmp;
    	}
    	for(int i=1;i<=n;i++)make(x[i]);
    	for(int i=1;i<=1000500;i++)dp[i]=0x7f7f7f7f;
    	dp[0]=0;
    	for(int zt=1;zt<(1LL<<20);zt++)
    	{
    		int maxx;
    		for(int i=20;i>=1;i--)if((zt>>i-1)&1==1){maxx=i;break;}
    		for(int q=1;q<=maxx;q++)dp[zt]=min(dp[zt],dp[(zt&((1<<q-1)-1))|(zt>>q)]+1);
    	}
    	for(int i=1;i<=cnt && prime[i]<=maxx;i++)
    	{
    		int begin=0,minn,minnn;
    		for(int j=1;j<=20;j++)if(a[i][j])begin|=(1<<(j-1));
    		minnn=dp[begin];
    		for(int j=1;j<=t[i];j++)minnn=min(minnn,dp[begin>>j]);
    		ans+=minnn;
    	} 
    	printf("%d",ans);
    	return 0;
    }
    
  • 相关阅读:
    powerdesigner反向MySQL5.1数据库 生成ER图
    Sublime Text 2 使用心得
    MyEclipse老是弹出problem occurred窗口
    Jquery ui Datepicker 的汉化
    jsp 中的getParameter和getAttribute
    jquery easyui
    struts2 annotation方式的下载(实用版)
    Sublime Text 2
    struts2框架搭建的三个步骤
    任意角度的平行四边形的碰撞检测原理
  • 原文地址:https://www.cnblogs.com/Tian-Xing-Sakura/p/13098964.html
Copyright © 2020-2023  润新知