topcoder srm 460 div1
problem1 link
设$f[i][j]$表示已经分配了answers中的前$i$个,分配给的问题的状态为 $j$的方案数。
其中状态可以用$n$位的三进制表示,0表示还未分配,1表示已分配是 Yes,2表示已分配是No.
problem2 link
假设$n$个城市为[0,n-1]。设$f[i][j][t]$表示在[0,i]个城市中已经选择了$j$个城市,选择了$t$个人的概率。
那么选择第$i+1$个城市的概率是$\frac{k-j}{n-i-1}$.
problem3 link
首先,如果一个连通图中存在两个环,也就是有$n$个顶点,$n+1$条边,那么从其中一个环上的某一点(这一点不属于另外一个环)到另一个环上的某一点(同样这一点也不属于前一个环)会有超过两条简单路径。所以满足条件的连通图要么是树,要么是只有一个环(也就是树上多一条边)。
假设给出的边使得$n$个顶点分成了$m$个连通分量,第$i$个连通分量中点的个数是$v_{i}$。
(1)假设最后是一棵树(前提是$m$个连通分量中每个连通分量中都没有环)。最后的答案是$T(m)=n^{m-2}\prod_{i=1}^{m}v_{i}$.这里要用到prufer编码。对于$m$个联通块的树,其prufer编码的长度为$m-2$。每个位置有$n$种情况,最后乘以叶子节点可以连出的边的数量。
比如$m=3,n=4$,分别是1-2,3,4。那么长度为1的prufer编码可以是{1},{2},{3},{4}.(推导过程参看上面的链接)
对于{1}来说,有两种:第一种: 1-3,1-4, 第二种1-3,2-4
对于{2}来说,有两种:第一种: 2-3,2-4, 第二种2-3,1-4
对于{3}来说,有两种:第一种: 3-1,3-4, 第二种3-2,3-4
对于{4}来说,有两种:第一种: 4-1,4-3, 第二种4-2,4-3
(2)有一个环。那么就要看这个环连通了$m$个联通块中的几个。
第一种: 1个,那么只需要枚举是第几个联通块;
第二种:2个,假设是联通块$a,b$.那么就是$C_{v_av_b}^{2}$
第三种:大于等于3个,假设是$k$个,那么是$\frac{(k-1)!}{2}\prod_{i=1}^{k}v_{ci}^{2}$,其中$ci$第第$i$个选出的联通块的编号。这里除以2是因为有翻转导致重复的情况。比如$k=4$时,$abcd$和$dcab$是一样的。
最后将连成的环看做一个连通分量,那么最后还有$m-k+1$个连通分量,将其连成一个树的方案为$T(m-k+1)$。
code for problem1
import java.util.*;
import java.math.*;
import static java.lang.Math.*; public class TheQuestionsAndAnswersDivOne { public int find(int n, String[] answers) { int[] p = new int[n + 2];
p[0] = 1;
for (int i = 1; i < p.length; ++ i) {
p[i] = p[i - 1] * 3;
} int[][] f = new int[answers.length][p[n]];
for (int i = 0; i < n; ++ i) {
int t = answers[0].equals("No")? 1 : 2;
f[0][t * p[i]] = 1;
}
for (int i = 1; i < answers.length; ++ i) {
int t = answers[i].equals("No")? 1 : 2;
for (int k = 0; k < p[n]; ++ k) {
if (f[i - 1][k] == 0) {
continue;
}
for (int j = 0; j < n; ++ j) {
int x = k / p[j] % 3;
if (x == 0 || x == t) {
int nk = k;
if (x == 0) {
nk += t * p[j];
}
f[i][nk] += f[i - 1][k];
}
}
}
}
int result = 0;
for (int i = 0; i < p[n]; ++ i) {
boolean tag = true;
for (int j = 0; j < n; ++ j) {
if (i / p[j] % 3 == 0) {
tag = false;
break;
}
}
if (tag) {
result += f[answers.length - 1][i];
}
}
return result;
}
}
code for problem2
import java.util.*;
import java.math.*;
import static java.lang.Math.*; public class TheFansAndMeetingsDivOne { public double find(int[] minJ, int[] maxJ, int[] minB, int[] maxB, int k) {
final int n = minJ.length;
int s1 = 0, s2 = 0;
for (int i = 0; i < n; ++ i) {
s1 += maxJ[i];
s2 += maxB[i];
}
final int m = Math.min(s1, s2) + 1;
double[][][] f = new double[n][k + 1][m];
double[][][] g = new double[n][k + 1][m]; f[0][0][0] = 1 - 1.0 * k / n;
for (int i = minJ[0]; i <= maxJ[0] && i < m; ++ i) {
f[0][1][i] = 1.0 * k / n / (maxJ[0] - minJ[0] + 1);
}
g[0][0][0] = 1 - 1.0 * k / n;
for (int i = minB[0]; i <= maxB[0] && i < m; ++ i) {
g[0][1][i] = 1.0 * k / n / (maxB[0] - minB[0] + 1);
} for (int i = 1; i < n; ++ i) {
for (int j = 0; j <= i && j <= k; ++ j) {
final double p = 1.0 * (k - j) / (n - i);
final double p1 = p / (maxJ[i] - minJ[i] + 1);
final double p2 = p / (maxB[i] - minB[i] + 1);
for (int t = 0; t < m; ++ t) {
f[i][j][t] += f[i - 1][j][t] * (1 - p);
g[i][j][t] += g[i - 1][j][t] * (1 - p);
if (j == k) {
continue;
}
for (int x = minJ[i]; x <= maxJ[i] && x + t < m; ++ x) {
f[i][j + 1][x + t] += f[i - 1][j][t] * p1;
}
for (int x = minB[i]; x <= maxB[i] && x + t < m; ++ x) {
g[i][j + 1][x + t] += g[i - 1][j][t] * p2;
}
}
}
} double result = 0;
for (int i = 0; i < m; ++ i) {
result += f[n - 1][k][i] * g[n - 1][k][i];
}
return result;
}
}
code for problem3
import java.util.*;
import java.math.*;
import static java.lang.Math.*; public class TheCitiesAndRoadsDivOne { static final int MOD = 1234567891; public int find(String[] map) {
final int n = map.length;
UnionSet unionSet = new UnionSet(n);
for (int i = 0; i < n; ++ i) {
for (int j = i + 1; j < n; ++ j) {
if (map[i].charAt(j) == 'Y') {
unionSet.merge(i, j);
}
}
}
List<Integer> list = new ArrayList<>();
int m = 0;
int circleNum = 0;
for (int i = 0; i < n; ++ i) {
if (unionSet.get(i) == i) {
++ m;
list.add(unionSet.vertexNum[i]);
circleNum += unionSet.edges[i] - unionSet.vertexNum[i] + 1;
}
}
if (circleNum > 1) {
return 0;
} if (m == 1) {
if (circleNum == 1 || list.get(0) <= 2) {
return 1;
}
return list.get(0) * (list.get(0) - 1) / 2 - (list.get(0) - 1) + 1;
} long[] p = new long[n + 1];
p[0] = 1;
for (int i = 1; i <= n; ++ i) {
p[i] = p[i-1] * n % MOD;
}
long result = p[m - 2];
for (int i = 0; i < m; ++ i) {
result = result * list.get(i) % MOD;
}
if (circleNum == 1) {
return (int)result;
} int sum = 0;
for (int i = 0; i < m; ++ i) {
int t = list.get(i);
sum += t * (t - 1) / 2 - (t - 1);
}
result = result * (sum + 1) % MOD; for (int i = 0; i < (1 << m); ++ i) {
int cnt = 0;
for (int j = 0; j < m; ++ j) {
if ((i & (1 << j)) != 0) {
++ cnt;
}
}
if (cnt < 2) {
continue;
}
long tmp = 1;
if (cnt == 2) {
for (int j = 0; j < m; ++ j) {
if ((i & (1 << j)) != 0) {
tmp *= list.get(j);
}
}
tmp = tmp * (tmp - 1) / 2;
}
else {
for (int j = 3; j <= cnt - 1; ++ j) {
tmp = tmp * j % MOD;
}
for (int j = 0; j < m; ++ j) {
if ((i & (1 << j)) != 0) {
tmp = tmp * list.get(j) * list.get(j) % MOD;
}
}
}
if (cnt == m) {
result = (result + tmp) % MOD;
continue;
}
tmp = tmp * p[(m - cnt + 1) - 2] % MOD;
long totVertex = 0;
for (int j = 0; j < m; ++ j) {
if ((i & (1 << j)) != 0) {
totVertex += list.get(j);
}
else {
tmp = tmp * list.get(j) % MOD;
}
}
tmp = tmp * totVertex % MOD;
result = (result + tmp) % MOD;
}
return (int)result;
} static class UnionSet {
int[] father = null;
int[] edges = null;
int[] vertexNum = null; UnionSet(int n) {
father = new int[n];
edges = new int[n];
vertexNum = new int[n];
for (int i = 0; i < n; ++ i) {
father[i] = i;
edges[i] = 0;
vertexNum[i] = 1;
}
} int get(int u) {
if (father[u] == u) {
return u;
}
return father[u] = get(father[u]);
} void merge(int u, int v) {
int fu = get(u);
int fv = get(v);
++ edges[fu];
if (fu == fv) {
return;
}
father[fv] = fu;
vertexNum[fu] += vertexNum[fv];
edges[fu] += edges[fv];
}
}
}
topcoder srm 460 div1的更多相关文章
- Topcoder SRM 643 Div1 250<peter_pan>
Topcoder SRM 643 Div1 250 Problem 给一个整数N,再给一个vector<long long>v; N可以表示成若干个素数的乘积,N=p0*p1*p2*... ...
- Topcoder Srm 726 Div1 Hard
Topcoder Srm 726 Div1 Hard 解题思路: 问题可以看做一个二分图,左边一个点向右边一段区间连边,匹配了左边一个点就能获得对应的权值,最大化所得到的权值的和. 然后可以证明一个结 ...
- topcoder srm 714 div1
problem1 link 倒着想.每次添加一个右括号再添加一个左括号,直到还原.那么每次的右括号的选择范围为当前左括号后面的右括号减去后面已经使用的右括号. problem2 link 令$h(x) ...
- topcoder srm 738 div1 FindThePerfectTriangle(枚举)
Problem Statement You are given the ints perimeter and area. Your task is to find a triangle wi ...
- Topcoder SRM 602 div1题解
打卡- Easy(250pts): 题目大意:rating2200及以上和2200以下的颜色是不一样的(我就是属于那个颜色比较菜的),有个人初始rating为X,然后每一场比赛他的rating如果增加 ...
- Topcoder SRM 627 div1 HappyLettersDiv1 : 字符串
Problem Statement The Happy Letter game is played as follows: At the beginning, several players ...
- Topcoder SRM 584 DIV1 600
思路太繁琐了 ,实在不想解释了 代码: #include<iostream> #include<cstdio> #include<string> #include& ...
- TopCoder SRM 605 DIV1
604的题解还没有写出来呢.先上605的. 代码去practice房间找. 说思路. A: 贪心,对于每个类型的正值求和,如果没有正值就取最大值,按着求出的值排序,枚举选多少个类型. B: 很明显是d ...
- topcoder srm 575 div1
problem1 link 如果$k$是先手必胜那么$f(k)=1$否则$f(k)=0$ 通过对前面小的数字的计算可以发现:(1)$f(2k+1)=0$,(2)$f(2^{2k+1})=0$,(3)其 ...
随机推荐
- 21.JQ的监听事件(点击div外面可以让它消失)
JQ的监听事件(点击div外面可以让它消失) //监听整个页面 $(document).bind("click", function() { //给需要的对象赋予事件 $(&quo ...
- Css预处理器---Less(三)
四.Color函数 1.less提供的颜色运算函数,颜色会被转换成HSL色彩空间,然后再通道级别进行操作,函数如下: lighten(@color, 10%); //return a color wh ...
- java数据结构和算法编程作业系列篇-数组
/** * 编程作业 2.1 向highArray.java程序(清单2.3)的HighArray类添加一个名为getMax()的方法,它返回 数组中最大关键字的值,当数组为空时返回-1.向main( ...
- virtual和abstract区别
virtual和abstract都是用来修饰父类的,通过覆盖父类的定义,让子类重新定义. 它们有一个共同点:如果用来修饰方法,前面必须添加public,要不然就会出现编译错误:虚拟方法或抽象方法是不能 ...
- 第一章 JS基础
1.JavaScript的作用:表单验证,减轻服务器压力动态效果动态改变页面内容 2.JavaScript的组成ECMAScript语法规定BOM对象模型(浏览器对象模型)DOM对象模型(文档对象模型 ...
- linux 下安装mysql-5.7.12-1.el6.x86_64.rpm-bundle.tar
-rw-rw-r--. hadoop hadoop Nov : mysql--.el6.x86_64.rpm-bundle.tar tar -xvf mysql-5.7.12-1.el6.x86_64 ...
- spring 框架的优点
谈spring 框架的优点就是说spring 框架2大核心技术的优点 1. 控制反转:控制反转是将对象的创建和管理交给spring容器,已经管理对象之间的依赖关系, 那么将对象的创建和生命周期的管理交 ...
- tcp_协议基础
具体7层 数据格式 功能与连接方式 典型设备 应用层 Application 数据Data 网络服务与使用者应用程序间的一个接口 终端设备(PC.手机.平板等) 表示层 Presentation ...
- bash 替换特殊字符
bash 替换特殊字符 PID=`netstat -tpln|grep `;PID=${PID#*LISTEN};PID=`echo $PID | sed -s "s/\/java//g&q ...
- 使用函数式编程消除重复无聊的foreach代码(Scala示例)
摘要:使用Scala语言为例,展示函数式编程消除重复无聊的foreach代码. 难度:中级 概述 大多数开发者在开发生涯里,会面对大量业务代码.而这些业务代码中,会发现有大量重复无聊的 foreach ...