题目大意是给你n个数,求相邻两数相乘不是完全平方数的排列数。
一开始看到这题的时候,本人便想给相乘为完全平方数的数对建边,然后就写萎了...
后来通过集体智慧发现这个重要性质:对于自然数a,b,c,若a*b为完全平方数,且b*c为完全平方数,那么a*c就是完全平方数。(我居然没想到)因此就可以对这n个数进行分组,使得每一组中两个数两两相乘为完全平方数,不同组的数两两相乘不是完全平方数。假设分成tot组,第i组的数的个数为num[i]。这也就等同于相同的数不能相邻的排列问题。
于是通过PY就得到了动规的做法:
定义数组dp[i,j],其中i表示前i组数,j表示有多少对相邻的同组的数(这也等价于有j个地方需要插入其他的数),而dp[i,j]就表示在当前状态下的方案数。那么最终答案就是dp[tot,0]。
定义m为前i-1组数的元素个数之和,在dp过程中维护。
当新加入第i组数的时候,把这num[i]个数分成k份(方案数是C(num[i]-1,k-1)),插入到m+1个空位中。
此时需要分类讨论:
在这m+1个空位中,有j个空位是特殊的,若插入其中会影响新生成的排列的相邻同组数的数目。于是设k份中的p份插入这j个空位中,剩下k-p份插入m+1-j个空位中。
就可以得到dp[i,j+num[i]-k-p]+=dp[i-1,j]*C(num[i-1],k-1)*C(j,p)*C(m+1-j,k-p);
这我一开始也不是很理解...
当然代码与这里有所差异。
注:因为dp是基于每一组数中的元素相同的前提的,所以最后答案还要乘以每一组数的A(num[i],num[i])。
 #include<bits/stdc++.h>
using namespace std;
const int N=,MOD=;
long long num[N],c[N][N];
long long dp[N][N],a[N];
int tmp,n,tot,example[N];
bool key;
bool ask(int x,int y)
{
long long re=;
re*=x;
re*=y;
long long f=sqrt(re);
if(f*f==re) return ;
return ;
}
int main()
{
cin>>n;
for(int i=;i<=n;i++)
{
cin>>tmp;
key=;
for(int j=;j<=tot;j++)
{
if(ask(tmp,example[j]))
{
num[j]++;
key=;
break;
}
}
if(key)
{
num[++tot]=;
example[tot]=tmp;
}
}
for(int i=;i<=n;i++)
c[i][]=;
for(int i=;i<=n;i++)
for(int j=;j<=i;j++)
{
c[i][j]=c[i-][j]+c[i-][j-];
c[i][j]%=MOD;
}
int m=;
a[]=;
for(int i=;i<=n;i++)
{
a[i]=a[i-]*i;
a[i]%=MOD;
}
dp[][]=;
long long temp,temp1;
for(int i=;i<=tot;i++)
{
for(int j=;j<n&&j<=m+;j++)
{
if(dp[i-][j]==) continue;
for(int k=;k<num[i];k++)
{
temp=dp[i-][j]*c[num[i]-][k];temp%=MOD;
for(int p=;p<=k+&&p<=j+num[i]--k;p++)
{
temp1=temp*c[j][p];temp1%=MOD;//本人因为数据溢出炸了几次
dp[i][j+num[i]--k-p]+=(temp1*c[m+-j][k+-p])%MOD;
dp[i][j+num[i]--k-p]%=MOD;
}
}
}
m+=num[i];
}
for(int i=;i<=tot;i++)
{
dp[tot][]*=a[num[i]];
dp[tot][]%=MOD;
}
cout<<dp[tot][]<<endl;
return ;
}

【做题】Codeforces Round #429 (Div. 2) E. On the Bench——组合问题+dp的更多相关文章

  1. Codeforces Round #429 (Div. 2) E. On the Bench

    E. On the Bench time limit per test 2 seconds memory limit per test 256 megabytes input standard inp ...

  2. Codeforces Round #429 (Div. 1) C. On the Bench(dp + 组合数)

    题意 一个长度为 \(n\) 的序列 \(A\) ,定义一个 \(1\) 到 \(n\) 的排列 \(p\) 是合法的,当且仅当 \(\forall i \in [1, n − 1], A_{p_i} ...

  3. CodeForces 840C - On the Bench | Codeforces Round #429 (Div. 1)

    思路来自FXXL中的某个链接 /* CodeForces 840C - On the Bench [ DP ] | Codeforces Round #429 (Div. 1) 题意: 给出一个数组, ...

  4. CodeForces 840B - Leha and another game about graph | Codeforces Round #429(Div 1)

    思路来自这里,重点大概是想到建树和无解情况,然后就变成树形DP了- - /* CodeForces 840B - Leha and another game about graph [ 增量构造,树上 ...

  5. CodeForces 840A - Leha and Function | Codeforces Round #429 (Div. 1)

    /* CodeForces 840A - Leha and Function [ 贪心 ] | Codeforces Round #429 (Div. 1) A越大,B越小,越好 */ #includ ...

  6. 水题 Codeforces Round #308 (Div. 2) A. Vanya and Table

    题目传送门 /* 水题:读懂题目就能做 */ #include <cstdio> #include <iostream> #include <algorithm> ...

  7. 水题 Codeforces Round #302 (Div. 2) A Set of Strings

    题目传送门 /* 题意:一个字符串分割成k段,每段开头字母不相同 水题:记录每个字母出现的次数,每一次分割把首字母的次数降为0,最后一段直接全部输出 */ #include <cstdio> ...

  8. 水题 Codeforces Round #299 (Div. 2) A. Tavas and Nafas

    题目传送门 /* 很简单的水题,晚上累了,刷刷水题开心一下:) */ #include <bits/stdc++.h> using namespace std; ][] = {" ...

  9. 水题 Codeforces Round #304 (Div. 2) A. Soldier and Bananas

    题目传送门 /* 水题:ans = (1+2+3+...+n) * k - n,开long long */ #include <cstdio> #include <algorithm ...

随机推荐

  1. url中是否加斜杠/

    通常来说,不加斜杠的形式(如”example.jsp”)请求的是相对于当前页面路径的资源 http://localhost:8080/webapp/examole:加斜杠的形式(”/example.j ...

  2. JavaScript(四):运算符&数据类型转换

    +:算符的加法:连接字符串 加法会将其它类型的值,自动转为字符串,然后再进行连接运算! var a=1+2; console.log('first: '+a); var a=1+2+'3';//先计算 ...

  3. Differencia (归并树)

    归并树,与我们原学过的归并排序是一样的原理,但是在那个的基础上进行扩展应用.首先每个节点储存了它每个节点所代表的点的有序序列,还有就是每个点里面包含的所有的b[i]在左右子树的排名辅助更新数据,还有一 ...

  4. 不能安装vmtools解决:一个命令安装

    https://blog.csdn.net/fly66611/article/details/77994339 换好源 sudo su apt-get update apt-get dist-upgr ...

  5. py3中reduce

    前因 因为 Guido 先生讨厌 reduce.(Because Guido hates it. ) 详细过程请翻阅原文:http://www.artima.com/forums/flat.jsp?f ...

  6. 设计模式之Builder(建造者)(转)

    Builder模式定义: 将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示. Builder模式是一步一步创建一个复杂的对象,它允许用户可以只通过指定复杂对象的类型和内容就可以 ...

  7. Autel MaxiSys Elite Diagnostic Tool Common problem solving methods

    1. updating MaxiFlash Elite to firmware 3.21? My maxisys communicate with the MaxiFlash J2534 but Ma ...

  8. 同行span标签设置display:inline-block;overflow:hidden垂直对齐问题

    1 问题描述:一个div包含 三个span 当span2 类样式设置如下图时,将导致垂直方向不对齐的情况 2解决方案: 将前面的也设置同样的样式 overflow:hidden; display:in ...

  9. QQ项目(续)

    1.项目查找好友的原理 sql:select * from qquser where account in(select friendAccount from friend where userAcc ...

  10. MySQL备份与恢复-mydumper

    上一片博文中,我们说明了mysqldump的备份与恢复.因为mysqldump是单线程导出,单线程恢复的,因此备份与恢复的时间比较长! 首先来安装mydumper: 下载源码:https://gith ...