zoukankan      html  css  js  c++  java
  • 【CF840C】On the Bench DP

    【CF840C】On the Bench

    题意:给你一个长度为n的数组{ai},定义一个1到n的排列是合法的,当且仅当对于$1le i <n$,$a_i imes a_{i+1}$不是完全平方数。求所有合法的排列个数。

    $nle 300,a_ile 10^9$

    题解:显然我们先把ai中的平方因子除掉,然后就变成了任意相邻两数不能相同的排列数。显然要将相同的数放到一起处理。

    考虑DP,令f[i][j][k]表示枚举到第i个数,一共有j个相邻的位置是相同的,在之前所有和ai相同的数中,有k个相邻的位置 的方案数。转移复杂度$O(n^3)$。

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    const ll P=1000000007;
    int n;
    int v[310];
    ll f[2][310][310];
    inline void upd(ll &x,const ll &y) {x+=y;	if(x>=P)	x%=P;}
    int main()
    {
    	scanf("%d",&n);
    	int i,j,k,d=0,tmp=0,t;
    	for(i=1;i<=n;i++)
    	{
    		scanf("%d",&t),v[i]=1;
    		for(j=2;j*j<=t;j++)	if(t%j==0)
    		{
    			tmp=0;
    			while(t%j==0)	tmp^=1,t/=j;
    			if(tmp)	v[i]*=j;
    		}
    		if(t>1)	v[i]*=t;
    	}
    	sort(v+1,v+n+1);
    	f[0][0][0]=1;
    	for(i=1;i<=n;i++)
    	{
    		if(v[i]>v[i-1])
    		{
    			for(j=0;j<=i;j++)	for(k=1;k<=tmp;k++)	upd(f[d][j][0],f[d][j][k]),f[d][j][k]=0;
    			tmp=0;
    		}
    		d^=1,memset(f[d],0,sizeof(f[d]));
    		for(j=0;j<=i;j++)	for(k=0;k<=tmp&&k<=j;k++)
    		{
    			upd(f[d][j+1][k+1],f[d^1][j][k]*(2*tmp-k));
    			if(j)	upd(f[d][j-1][k],f[d^1][j][k]*(j-k));
    			upd(f[d][j][k],f[d^1][j][k]*(i-(2*tmp-k)-(j-k)));
    		}
    		tmp++;
    	}
    	printf("%lld",f[d][0][0]);
    	return 0;
    }
  • 相关阅读:
    大一励志的我,现在已经大三了
    Jenkins+K8s实现持续集成
    Jenkins搭建自动化测试环境
    软件开发式样书 6
    软件开发式样书 5
    软件开发式样书 4
    软件开发式样书 3
    软件开发式样书 2
    软件开发式样书 1
    Git学习笔记
  • 原文地址:https://www.cnblogs.com/CQzhangyu/p/8283104.html
Copyright © 2011-2022 走看看