首页 > 其他分享 >【题解 CF840C & P4448】 On the Bench & 球球的排列

【题解 CF840C & P4448】 On the Bench & 球球的排列

时间:2023-10-18 20:46:27浏览次数:37  
标签:种颜色 平方 颜色 球球 题解 long times permutation Bench

On the Bench

题面翻译

给定一个序列 \(a(a_i\le 10^9)\),长度为 \(n(n\le 300)\)。

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

题目描述

A year ago on the bench in public park Leha found an array of $ n $ numbers. Leha believes that permutation $ p $ is right if for all $ 1<=i<n $ condition, that $ a_{pi}·a_{pi+1} $ is not perfect square, holds. Leha wants to find number of right permutations modulo $ 10^{9}+7 $ .

输入格式

First line of input data contains single integer $ n $ ( $ 1<=n<=300 $ ) — length of the array.

Next line contains $ n $ integers $ a_{1},a_{2},...\ ,a_{n} $ ( $ 1<=a_{i}<=10^{9} $ ) — found array.

输出格式

Output single integer — number of right permutations modulo $ 10^{9}+7 $ .

样例 #1

样例输入 #1

3
1 2 4

样例输出 #1

2

样例 #2

样例输入 #2

7
5 2 4 2 4 1 1

样例输出 #2

144

提示

For first example:

$ [1,2,4] $ — right permutation, because $ 2 $ and $ 8 $ are not perfect squares.

$ [1,4,2] $ — wrong permutation, because $ 4 $ is square of $ 2 $ .

$ [2,1,4] $ — wrong permutation, because $ 4 $ is square of $ 2 $ .

$ [2,4,1] $ — wrong permutation, because $ 4 $ is square of $ 2 $ .

$ [4,1,2] $ — wrong permutation, because $ 4 $ is square of $ 2 $ .

$ [4,2,1] $ — right permutation, because $ 8 $ and $ 2 $ are not perfect squares.

解题思路

首先,对于三个数 \(a_i,a_j,a_u\) , \(a_i \times a_j\) 为完全平方数, \(a_i \times a_u\) 为完全平方数,显然有 \(a_j \times a_u\) 为完全平方数。
根据这条性质,那么,对于一堆数 \(a_1,a_2,a_3,...,a_m\) 中 \(a_1 \times a_2,a_2\times a_3,...,a_{m-1} \times a_m\) 为完全平方数,这堆数中任意两个数相乘都为完全平方数。
所以,我们考虑将数变成几堆,每堆内的数相乘为完全平方数,每堆中的数与他堆中的数不为完全平方数,也就可以放在一起。
用二分来求每两个数相乘是否为完全平方数,将相乘为完全平方数的放成一堆,给每堆里的数染色,相同堆染同色,问题变成:将一些数放成一排,且相邻颜色不同的方案数?
由于 \(n\le 300\) ,考虑 \(DP\) 。
按颜色大小从小到大放,放成像 \(1,1,1,2,2,3,...\) 这样的形式。
所以考虑 \(f_{i,j,k}\) 表示放到第 \(i\) 位,非当前颜色的冲突数 \(j\) ,当前颜色的冲突数 \(k\) 。
冲突数指的就是颜色相同的放成相邻的个数,例如 \(3,3,3\) 有 \(2\) 个冲突。
很显然,初始化 \(f_{0,0,0} =1\) ,求 \(f_{n,0,0}\) 。
一种颜色一种颜色的放,采取插入 \(DP\) 的形式 ,将放完的紧密的靠在一起,就会出现有冲突的,再一步步推到没冲突的。
考虑状态转移方程,分情况讨论:

1.第 \(i\) 位颜色与第 \(i-1\) 种颜色不同,放到两种不同颜色的中间。

所以 \(k\) 必为 \(0\) ,枚举非上一种颜色的冲突数 \(i\),每一次可放到 \(((i-1)+1)-j=i-j\) 个位置上,有:

\[f_{i,j,0}=f_{i-1,u,j-u} \times (i-j) , u \in [0,j] \]

2.第 \(i\) 位颜色与第 \(i-1\) 种颜色不同,放到两种相同颜色的中间。

\(k\) 照旧为 \(0\) ,枚举非上一种颜色的冲突数,每次可放到 \(j+1\) 个位置上,有:

\[f_{i,j,0}=f_{i-1,u,j-u+1} \times (j+1) , u \in [0,j+1] \]

所以第 \(i\) 位颜色与第 \(i-1\) 种颜色不同时,状态转移方程为:

\[f_{i,j,0} = \begin{cases} f_{i-1,u,j-u} \times (i-j) , u \in [0,j] \\ f_{i-1,u,j-u+1} \times (j+1) , u \in [0,j+1] \end{cases} \]

3.第 \(i\) 位颜色与第 \(i-1\) 种颜色相同,放到与第 \(i\) 为颜色的数旁边。

设第 \(i\) 种颜色已经放了 \(q\) 个。
\(j\) 不变,\(k\) 增加 \(1\),可放到 \(2 \times q - (k-1) =2 \times q - k + 1\) 个位置上,有:

\[f_{i,j,k} = f_{i-1,j,k-1} \times (2 \times q-k+1), k\in [1,q] \]

4.第 \(i\) 位颜色与第 \(i-1\) 种颜色相同,放到两种与第 \(i\) 种颜色的数的中间。

\(j\) 减 \(1\) ,\(k\) 不变,可放到 \(j+1\) 个位置上,有:

\[f_{i,j,k} = f_{i-1,j+1,k} \times (j+1) ,k \in [0,q] \]

5.第 \(i\) 位颜色与第 \(i-1\) 种颜色相同,放到两个异色且都不与第 \(i\) 位颜色相同的数的中间。

\(j\) 不变,\(k\) 也不变,可放到 \(((i-1)+1)-j-(2 \times q-k) =i-j-2 \times q + k\) 个位置上,有:

\[f_{i,j,k} = f_{i-1,j,k} \times (i-j-2 \times q + k) , k \in [0,q] \]

所以第 \(i\) 位颜色与第 \(i-1\) 种颜色相同时,状态转移方程为:

\[f_{i,j,k} = \begin{cases} f_{i,j,k} = f_{i-1,j,k-1} \times (2 \times q-k+1), k\in [1,q] \\ f_{i,j,k} = f_{i-1,j+1,k} \times (j+1) ,k \in [0,q] \\ f_{i,j,k} = f_{i-1,j,k} \times (i-j-2 \times q + k) , k \in [0,q] \end{cases} \]

时间复杂度 \(O(n^3)\) ,空间复杂度 \(O(n^3)\) ,使用滚动数组可优化至 \(O(n^2)\) 。

Code

#include<bits/stdc++.h>
using namespace std;
const long long mod=1e9+7;
long long n,f[2][305][305],a[305],d[305],p=0; 
bool check(long long x)
{
	long long l=1,r=1e9,mid;
	while(l<=r)
	{
		mid=(l+r)>>1;
		if(mid*mid==x)return true;
		if(mid*mid<x)l=mid+1;
		else r=mid-1;
	}
	return false;
} 
int main()
{
	long long q=0;
	scanf("%lld",&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%lld",&a[i]);
	}
	for(int i=1;i<=n;i++)
	{
		for(int j=i+1;j<=n;j++)
		{
			if(check(a[i]*a[j]))
			{
				if(!d[i])d[i]=++q;
				d[j]=d[i];
			}
		}
	}
	for(int i=1;i<=n;i++)a[i]=d[i]>0?d[i]:(++q);
	q=0;
	sort(a+1,a+n+1);
	f[0][0][0]=1;
	for(int i=1;i<=n;i++)
	{
		p^=1;
		if(a[i]!=a[i-1])
		{
			q=1;
			for(int j=0;j<=i-1;j++)
			{
				for(int u=0;u<=j;u++)f[p][j][0]+=(f[p^1][u][j-u]*(i-j)+f[p^1][u][j-u+1]*(j+1))%mod,f[p][u][j-u]%=mod;
				f[p][j][0]+=f[p^1][j+1][0]*(j+1);
				f[p][j][0]%=mod; 
			}
		}	
		else
		{
			for(int j=0;j<=i-1;j++)
			{
				for(int u=0;u<=i-1;u++)
				{
					if(u>=1)f[p][j][u]+=f[p^1][j][u-1]*(2*q-u+1)%mod;
					f[p][j][u]+=f[p^1][j+1][u]*(j+1)%mod;
					f[p][j][u]+=f[p^1][j][u]*(i-j-2*q+u)%mod;
					f[p][j][u]%=mod; 
				}
			}
			q++;
		}
		for(int j=0;j<=i;j++)
		{
			for(int u=0;u<=i;u++)f[p^1][j][u]=0;
		}
	}
	cout<<f[n&1][0][0];
	








  return 0;
}

标签:种颜色,平方,颜色,球球,题解,long,times,permutation,Bench
From: https://www.cnblogs.com/dijah/p/17773271.html

相关文章

  • P9506 题解
    blog。Firstsolution/kx。容易想到断环成链。打开标签发现是DP,于是就可以DP了。code,时间复杂度\(O(\text{能过})\)。......
  • 算法笔记-有效括号序列题解
    描述给出一个仅包含字符'(',')','{','}','['和']',的字符串,判断给出的字符串是否是合法的括号序列。括号必须以正确的顺序关闭,"()"和"()[]{}"都是合法的括号序列,但"(]"和"([)]"不合法。数据范围:字符串长度0≤n≤10000要求:空间复杂度O(n),时间复杂......
  • NOIP2018PJ T3 摆渡车(2023.10第二版题解)
    题目链接 题意:时间轴上分布着$n$位乘客($1\len\le500$),$i$号乘客的位置为$t_i$(0\let_i\le4\times10^6),用互相距离不小于$m$的车次将时间轴分为若干部分,并管辖以自己为右端点的这个区间(除了第一趟车包括$0$,其他车次左开右闭),求最小费用和。每个车次的费用来自:管辖区间内所......
  • AT_arc100_b 题解
    题意这道题是让我们把一段区间分成四个不为空的连续子序列,并算出每个区间的和,最后用四个和的最大值减去最小值,算出最终答案。分析大家首先想到的肯定是暴力法用三个循环枚举四个区间,对于每一个区间,在单独算和,这样的时间复杂度$O(n^4)$,肯定会超时。现在我们进行优化:最后求和的......
  • P4899 [IOI2018] werewolf 狼人 题解
    P4899[IOI2018]werewolf狼人题解题目描述省流:\(n\)个点,\(m\)条边,\(q\)次询问,对于每一次询问,给定一个起点\(S\)和终点\(T\),能否找到一条路径,前半程不能走\(0\thicksimL-1\)这些点,后半程不能走\(R+1\thicksimN-1\)这些点。中途必须有一个点在\(L\thicksimR\)之......
  • AT_abc134_d Preparing Boxes题解
    简述题意这什么破翻译,看了AtCoder的英文才看懂。给定一个长度为\(n\)序列\(a\),要求构造一个数列\(b\),使得对于任意\(i\),满足:\(1\lei\len\)将\(b\)序列下标为\(i\)的倍数的值相加使得这个总和模2等于\(a_i\)。求序列\(b\)中值为1的个数与值为1......
  • P9700题解
    思路看数据范围,发现范围很小,直接用搜索。搜索时枚举每个点,如果有棋子就枚举方向,如果这个方向合法,则将剩余棋子数减一,继续搜索。搜索时参数只需要传当前棋子数就行了。有以下几点需要注意多组数据每次需要初始化。判断是否合法时要注意。每次记得回溯棋子。ACCODE......
  • SP26719题解
    考虑动态规划。思路设\(dp_{i,j}\)为\((1,1)\)到\((i,j)\)的方案数,而如果要到这个点,肯定是从左边和上边来。所以递推公式为:\(dp_{i,j}=dp_{i,j-1}+dp_{i-1,j}\)。预处理:将横或纵坐标为1的点赋值为1,因为到达这些点的只有一种方法。注意:每次需要清零数组。ACC......
  • CF1873B题解
    这题其实可以数学方法差小积大解决。差越小积越大,那肯定是让最小的数加一啦。将所有数的积除以最小值再乘上最小值加一。#include<bits/stdc++.h>usingnamespacestd;signedmain(){ intT; cin>>T; while(T--){ longlongcnt=0,n,a[10],minn=LONG_LONG_MAX,ans=1; c......
  • CF1868C Travel Plan 题解
    原题翻译发现所有长度相同的简单路径的权值可能情况相同,且最长的简单路径长度为\(O(\logn)\)级别,考虑维护所有长度的简单路径在一棵树上出现的次数,每种简单路径的权值在所有树上出现的次数,相乘即使答案。我们考虑长度为\(x\)的路径对答案的贡献,考虑枚举这条路径的贡献\(......