• CF1028H Make Square 题解


    Codeforces
    Luogu

    Description.

    定义序列是优秀的,当且仅当存在两个数它们之积是完全平方。
    多次询问,每次询问对 \([l,r]\) 这个序列进行 \(\times p,\div p(p\in\text{prime})\),最少几次可以让它变优秀。
    \(n\approx 10^5,q\approx 10^6,a_i\approx 5\times 10^6\)

    Solution.

    经典套路,先把 \(p^2\) 删掉,然后就相当于要让两个数相同。
    剩下的数不会有超过 \(7\) 个质因数,设 \(x\) 质因数个数是 \(f_x\)
    \(x\) 变成 \(y\) 的步数显然是 \(f_x+f_y-f_{\gcd(x,y)}\)
    这启发我们枚举 \(\gcd(x,y)\)
    不超过 \(7\) 个不同质因数,那因数个数是 \(2^7\)
    所以可以离线然后对每个因数维护最后一个出现次数。
    然后维护答案为 \(k\) 时可行最右端点位置。
    然后直接枚举答案就行了。
    总复杂度 \(O(2^7n+14Q+n\log V)\)

    Coding.

    点击查看代码
    //Coded by Kamiyama_Shiki on 2021.11.16 {{{
    //是啊……你就是那只鬼了……所以被你碰到以后,就轮到我变成鬼了
    #include<bits/stdc++.h>
    #define debug(...) fprintf(stderr,__VA_ARGS__)
    using namespace std;typedef long long ll;
    template<typename T>inline void read(T &x)
    {
    	x=0;char c=getchar(),f=0;
    	for(;c<48||c>57;c=getchar()) if(!(c^45)) f=1;
    	for(;c>=48&&c<=57;c=getchar()) x=(x<<1)+(x<<3)+(c^48);
    	f?x=-x:x;
    }
    template<typename T,typename...L>inline void read(T &x,L&...l) {read(x),read(l...);}//}}}
    const int N=194599,Q=1049659;
    const int V=5032108;int pr[V],pc,ls[V];char pv[V];//prinit{{{
    inline void prinit(int n=V-1)
    {
    	pv[1]=1,ls[1]=0;for(int i=1;i<=n;i++)
    	{
    		if(!pv[i]) pr[++pc]=i,ls[i]=i;
    		for(int j=1;j<=pc&&i*pr[j]<=n;j++) {pv[i*pr[j]]=1,ls[i*pr[j]]=pr[j];if(i%pr[j]==0) break;}
    	}
    }//}}}
    int n,a[N],dp[V][8],rs[15],q[257],lg[257],sz[257];
    int m,ans[Q];vector<pair<int,int> >qr[Q];
    int main()
    {
    	read(n,m),prinit();for(int i=1;i<=n;i++) read(a[i]);
    	for(int i=1,l,r;i<=m;i++) read(l,r),qr[r].push_back(make_pair(l,i));
    	for(int i=1;i<=n;i++) for(int x=a[i];ls[x];) if(a[i]/ls[x]%ls[x]) x/=ls[x];else a[i]/=ls[x]*ls[x],x/=ls[x]*ls[x];
    	for(int i=0;i<8;i++) lg[1<<i]=i;
    	sz[0]=0;for(int i=1;i<256;i++) sz[i]=sz[i^(i&(-i))]+1;
    	for(int i=1;i<=n;i++)
    	{
    		int x=a[i],qt=0;while(ls[x]) q[1<<qt]=ls[x],qt++,x/=ls[x];
    		q[0]=1;for(int j=1;j<(1<<qt);j++) q[j]=q[j^(j&(-j))]*q[j&(-j)];
    		for(int j=0;j<(1<<qt);j++)
    		{
    			int now=qt-(sz[j]<<1),vl=q[j];
    			for(int k=0;k<=7;k++) rs[k+now]=max(rs[k+now],dp[vl][k]);
    			dp[vl][qt]=i;
    		}
    		//debug("%d : ",i);for(int k=0;k<=7;k++) debug("%d%c",rs[k],k==7?'\n':' ');
    		for(size_t j=0;j<qr[i].size();j++) for(int k=0;k<=14;k++)
    			if(rs[k]>=qr[i][j].first) {ans[qr[i][j].second]=k;break;}
    	}
    	for(int i=1;i<=m;i++) printf("%d\n",ans[i]);
    	return 0;
    }
    
  • 相关阅读:
    echarts学习:简单柱状图和折线图
    pymongo的正则查询
    nginx学习:配置文件及其组成
    nginx实战:flaks + uwgsi + nginx部署
    nginx:学习三
    celery使用实例
    luoguP2742 二维凸包 / 圈奶牛Fencing the Cows
    AtCoder Grand Contest 025 Problem D
    luoguP3960 [noip2017]列队(树状数组)
    bzoj3223: Tyvj 1729 文艺平衡树(splay翻转操作)
  • 原文地址:https://www.cnblogs.com/pealfrog/p/15572290.html
Copyright © 2020-2023  润新知