• CF 980D Perfect Groups(数论)


    CF 980D Perfect Groups(数论)

    一个数组a的子序列划分仅当这样是合法的:每个划分中的任意两个数乘积是完全平方数。定义a的权值为a的最小子序列划分个数。现在给出一个数组b,问权值为i的b的子串个数。

    这题意真不是人类智慧能轻易描述的。据说此题在比赛场上读题30min,做题5min,做完还WA。果然是坑题。

    如果有两个数a和b,a和b的乘积是完全平方数,那么如果a有因子x2,那么x2就可以去掉,使a变成a/x^2,结论依然成立。因此我们把所有数的质因子次数mod2,可以发现结论仍然不变。

    因此,在一个划分内的数必须完全相同或者有数为零(涉及乘除法一定要考虑零啊啊啊)。n^2dp即可。

    #include <cstdio> 
    #include <algorithm>
    using namespace std;
    
    const int maxn=5005;
    int n, a[maxn], b[maxn], cnt[maxn];  //cnt[i]储存i有几个 
    int k, ans[maxn], id0;
    
    int deal(int x){
    	int flag;
    	if (x<0) x=-x, flag=-1; else flag=1;
    	for (int i=2; i*i<=x; ++i) 
    		while (x%(i*i)==0) x/=i*i;
    	return x*flag;
    }
    
    int main(){
    	scanf("%d", &n); int t; id0=-1;
    	for (int i=1; i<=n; ++i){
    		scanf("%d", &t), a[i]=b[i]=deal(t);
    		if (!a[i]) id0=0;
    	}
    	sort(b+1, b+1+n); 
    	if (!id0) id0=lower_bound(b+1, b+1+n, 0)-b;
    	for (int i=1; i<=n; ++i)
    		a[i]=lower_bound(b+1, b+1+n, a[i])-b;
    	for (int i=1; i<=n; ++i){
    		for (int j=1; j<=n; ++j) cnt[j]=0; k=0;  //k:[i,j]不同元素的数目 
    		for (int j=i; j<=n; ++j){
    			if (a[j]==id0){
    				if (!k) ++ans[1]; else ++ans[k];
    				continue;	
    			}
    			if (!cnt[a[j]]) ++k;
    			++cnt[a[j]]; ++ans[k];
    		}
    	}
    	for (int i=1; i<=n; ++i) printf("%d ", ans[i]);
    	return 0;
    }
    
  • 相关阅读:
    hdu2155 小黑的镇魂曲(dp)
    hdu2155 小黑的镇魂曲(dp)
    hdu2158 最短区间版大家来找碴
    hdu2158 最短区间版大家来找碴
    hdu2102 水搜索
    hdu2102 水搜索
    hdu 2058 枚举区间和个数
    hdu 2058 枚举区间和个数
    hdu4982 暴搜+剪枝(k个数和是n,k-1个数的和是平方数)
    hdu4982 暴搜+剪枝(k个数和是n,k-1个数的和是平方数)
  • 原文地址:https://www.cnblogs.com/MyNameIsPc/p/9053087.html
Copyright © 2020-2023  润新知