• [CF840C] On the Bench


    问题描述

    给定一个序列 (a(a_ile 10^9)),长度为 (n(nle 300))

    试求有多少 1 到 (n) 的排列 (p_i),满足对于任意的 (2le ile n)(a_{p_{i-1}} imes a_{p_i}) 不为完全平方数,答案对 (10^9+7) 取模。

    样例输入

    3
    1 2 4

    样例输出

    2

    解析

    一个数可以拆成一个完全平方数乘上另一个数。不妨将每个数的完全平方数因子去掉,问题就变成了如何使一个序列的相邻两个数不同。

    考虑从小到大依次放数。设 (f_{i,j,k}) 表示当前考虑第 (i) 个数,一共有 (j) 个数相邻,其中 (k) 个与当前数相同。记 (cnt) 表示前面有几个数和自己相同。有如下几种情况:

    • 当前数放在某个和自己相同的数旁边。容斥一下,有(f_{i,j+1,k+1}=f_{i-1,j,k} imes (2*cnt-k))
    • 放在某两个相邻的数中间,但不跟自己相同。(f_{i,j-1,k}=f_{i-1,j,k} imes (j-k))
    • 放在了其他地方。(f_{i,j,k}=f_{i-1,j,k} imes [i-(2cnt-k)-(j-k)])

    当前数与前面放的数不同时,注意对DP数组进行修改。

    代码

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define int long long
    #define N 302
    using namespace std;
    const int mod=1000000007;
    int n,i,j,k,a[N],f[2][N][N],x,cnt;
    int read()
    {
    	char c=getchar();
    	int w=0;
    	while(c<'0'||c>'9') c=getchar();
    	while(c<='9'&&c>='0'){
    		w=w*10+c-'0';
    		c=getchar();
    	}
    	return w;
    }
    signed main()
    {
    	n=read();
    	for(i=1;i<=n;i++) a[i]=read();
    	for(i=1;i<=n;i++){
    		for(j=2;j*j<=a[i];j++){
    			while(a[i]%(j*j)==0) a[i]/=j*j;
    		}
    	}
    	sort(a+1,a+n+1);
    	f[0][0][0]=1;
    	for(i=2;i<=n;i++){
    		x^=1;
    		memset(f[x],0,sizeof(f[x]));
    		if(a[i]==a[i-1]) cnt++;
    		else{
    			for(j=0;j<i-1;j++){
    				for(k=1;k<=min(cnt,j);k++){
    					f[x^1][j][0]=(f[x^1][j][0]+f[x^1][j][k])%mod;
    					f[x^1][j][k]=0;
    				}
    			}
    			cnt=0;
    		}
    		for(j=0;j<i-1;j++){
    			for(k=0;k<=min(cnt,j);k++){
    				if(j>0) f[x][j-1][k]=(f[x][j-1][k]+f[x^1][j][k]*(j-k)%mod)%mod;
    				f[x][j][k]=(f[x][j][k]+f[x^1][j][k]*(i-2*cnt-j+2*k)%mod)%mod;
    				f[x][j+1][k+1]=(f[x][j+1][k+1]+f[x^1][j][k]*(2*cnt-k)%mod)%mod;
    			}	
    		}
    	}
    	printf("%lld
    ",f[x][0][0]);
    	return 0;
    }
    
    
  • 相关阅读:
    linux 程序后台运行
    小型网站架构技术点(简要)
    rsync安装与配置使用 数据同步方案(centos6.5)
    nfs的原理 安装配置方法 centos6.5
    centos 6.5 升级到 python2.7
    ntpdate 设置时区(注意本地时区要设置正确)
    关于umask的计算方式(简单任性)
    No space left on device(总结)
    lsof 查看打开了一个文件的有哪些进程 统计那个进程打开的文件最多
    作用域是什么?
  • 原文地址:https://www.cnblogs.com/LSlzf/p/13554425.html
Copyright © 2020-2023  润新知