2013 Multi-University Training Contest 6
HDU-4655 Cut Pieces
题意:有N个格子能够被涂色,每个格子能够涂1-ai 种颜色,当N=6,涂色方案:112233 认为方案中共有3个颜色块;涂色方案:121212 认为方案中共有6个颜色块。所谓颜色块也就是整个涂色方案中相同连续的颜色被视作为一个颜色块。问如何安排 ai 的排列使得所有方案颜色块之和最大。
分析:从反面求解,首先能够产生的方案数一共有a1*a2*a3*...*an种,每种方案在没有相邻颜色认为为同一颜色块的情况下,颜色块的数量均为n。那么如何减掉重复计算的。可以考虑到任何一个k长连续颜色块,若统计其相邻格子颜色相同数量为k-1,如果减去这些相邻格子数正好满足同一颜色块只被统计一次。
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std; typedef long long LL;
const int N = int(1e6)+;
const int mod = int(1e9)+;
int n, seq[N];
int f[N], t[N]; void solve() {
int tot = , rep = ;
sort(seq, seq+n);
f[] = seq[], t[n-] = seq[n-], t[n] = ;
for (int i = ; i < n; ++i) {
f[i] = (1LL*f[i-]*seq[i]) % mod;
}
for (int i = n-; i >= ; --i) {
t[i] = (1LL*t[i+]*seq[i]) % mod;
}
for (int i = ; i < n; ++i) {
tot = (1LL*tot*seq[i]) % mod;
}
for (int i = n-; i > n/; --i) {
rep = (rep + 2LL*f[i-]*t[i+]) % mod;
}
if (!(n&)) rep = (rep + 1LL*f[n/-]*t[n/+]) % mod;
printf("%d\n", ((1LL*tot*n-rep)%mod+mod)%mod);
} int main() {
int T;
scanf("%d", &T);
while (T--) {
scanf("%d", &n);
for (int i = ; i < n; ++i) {
scanf("%d", &seq[i]);
}
solve();
}
return ;
}
HDU-4657 Find Permutation
题意:给定一个序列b,求a、c两个序列,满足:(a[i]+b[i]) % n = c[i],其中a、c 数组均为[0, n-1]的排列。
分析:采用构造的方式,初始化a[i] = c[i] = i,同时维护一个记录a中元素所在位置的数组。对于枚举到 i 位置保持1 到 i-1 中(a[i]+b[i]) % n = c[i]成立。对于 i 号位置,根据b[i]和c[i]计算出所需要的a[j],通过 a 数组的索引数组快速找到所需元素的下标 j,如果 j 大于等于枚举的位置,那么继续往后枚举 i,因为该位置我们还未做处理;否则注定要破坏之前已经维护好的关系,因此需要交换一些元素,并且重新维护好原来的值。
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std; const int N = int(1e5)+;
int n;
int a[N], b[N], c[N], idxa[N]; int main() {
int _; scanf("%d", &_);
while (_--) {
scanf("%d", &n);
for (int i = ; i < n; ++i) scanf("%d", &b[i]);
for (int i = ; i < n; ++i) a[i] = c[i] = idxa[i] = i;
for (int i = ; i < n; ++i) {
int cur = i;
while ((a[cur]+b[cur])%n != c[cur]) { // 当前位不匹配
int nxt = idxa[(c[cur]-b[cur]+n)%n]; // 获得要调整的位置
swap(a[cur], a[nxt]); // 将a数组进行数字的调整
swap(idxa[a[cur]], idxa[a[nxt]]);
if (nxt > i) break; // 需要调整位置还尚未更新,否则打破了之前维护好的结果
swap(c[i+], c[nxt]);
cur = nxt;
}
}
for (int i = ; i < n; ++i) printf(i == ? "%d" : " %d", a[i]); puts("");
for (int i = ; i < n; ++i) printf(i == ? "%d" : " %d", c[i]); puts("");
}
return ;
}
HDU-4658 Integer Partition
题意:求一个整数(N<=100000)的整数分拆数,要求每一种分拆方案中不能够存在某个数出现K次或K次以上。例如N=4,K=2,那么只有4 = 4 一种分拆方式。
分析:介绍整数分拆及相关的资料:
整数分拆:http://zh.wikipedia.org/wiki/%E6%95%B4%E6%95%B8%E5%88%86%E6%8B%86
五边形数定理:http://zh.wikipedia.org/wiki/%E4%BA%94%E9%82%8A%E5%BD%A2%E6%95%B8%E5%AE%9A%E7%90%86
欧拉函数(复变函数):http://zh.wikipedia.org/wiki/%E6%AD%90%E6%8B%89%E5%87%BD%E6%95%B8_(%E8%A4%87%E8%AE%8A%E5%87%BD%E6%95%B8)
母函数:http://zh.wikipedia.org/wiki/%E6%AF%8D%E5%87%BD%E6%95%B0
五角数:http://zh.wikipedia.org/wiki/%E5%BB%A3%E7%BE%A9%E4%BA%94%E9%82%8A%E5%BD%A2%E6%95%B8#.E5.BB.A3.E7.BE.A9.E4.BA.94.E9.82.8A.E5.BD.A2.E6.95.B8
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std; const int mod = int(1e9)+;
const int N = int(1e5);
int q[N+], p[N+]; // 其中q[i]表示欧拉函数的第i次方的系数,其值为广义五边形数
// p[i]为整数 i 的拆分方案数
int n, k; void prepare() {
int a, b, sign;
q[] = ;
for (int i = , j = ; ; ++i, j+=) {
sign = (i & ) ? - : ;
q[j] = sign * (*i*i-i) / ;
q[j+] = sign * (*i*i+i) / ;
if (abs(q[j+]) >= N) break;
} // 求出欧拉函数的指数项,并且保存好符号
p[] = , p[] = , p[] = ;
for (int i = ; i <= N; ++i) {
for (int j = ; ; ++j) {
sign = (j & ) ? : -;
a = (*j*j-j)/, b = (*j*j+j)/;
if (a <= i) p[i] = (p[i]+sign*p[i-a]) % mod;
else break;
if (b <= i) p[i] = (p[i]+sign*p[i-b]) % mod;
else break;
}
} // O(n^1.5)计算出所有整数分拆系数p[]
} int solve(int n, int k) {
int sign, ret = ;
for (int i = ; ; ++i) { // 由于欧拉函数的稀疏性,因此枚举欧拉函数的指数项与对应的整数分拆母函数结合
if (k * abs(q[i]) > n) break;
sign = q[i] >= ? : -;
ret = (ret + sign*p[n-k*abs(q[i])]) % mod;
}
return (ret + mod) % mod;
} int main() {
prepare();
int T;
scanf("%d", &T);
while (T--) {
scanf("%d %d", &n, &k);
printf("%d\n", solve(n, k));
}
return ;
}
HDU-4661 Message Passing
题意:给定一棵树,N个节点,每个节点都拥有一个唯一的信息,现在规定没一个时刻只能够由某一个人将信息传送给相邻的节点,每次传送能够传递他所收到的所有信息。问使得传递时间最短的传送方案共有多少种?
分析:很明显,当所有的信息都汇聚到一个人,然后再由这一个人传送出去是最优的,也就是每条边被传递两次。选择一个点作为根节点,然后通过树形dp得到方案数。在选定了根之后,每颗子树的根均为收到子节点的信息后再向上层传递,在统计多棵子树的时候要考虑到一些组合情况。做完之后再从根开始往下更新一次,目的是得到以每个节点为根的方案数。
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <algorithm>
#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std; typedef long long LL;
const int mod = int(1e9)+;
const int N = ;
int n;
int num[N], dp[N];
int f[N]; // 阶乘
// num[i]记录i节点在指定1为根下有多少节点
// dp[i]表示i节点在指定1为根下有多少种信息汇集的方式
struct Node {
int v, next;
}e[N];
int head[N], idx; void prepare() {
f[] = ;
for (int i = ; i < N; ++i) {
f[i] = (1LL*f[i-]*i) % mod;
}
} void insert(int a, int b) {
e[idx].v = b, e[idx].next = head[a];
head[a] = idx++;
} int pow(int a, int b) {
int ret = ;
while (b) {
if (b & ) ret = (1LL*ret*a) % mod;
b >>= ;
a = (1LL*a*a) % mod;
}
return ret;
} int inv(int x) { // 逆元
return pow(x, mod-);
} int C(int m, int n) { // 计算组合数c(m, n)
return (1LL*f[n]*inv((1LL*f[m]*f[n-m])%mod))%mod;
} void dfs1(int p, int u) { // 从下往上更新某个节点为根的信息汇集方案数
if (head[u] == -) {
dp[u] = ;
num[u] = ;
return;
}
int tot = , tmp = ;
for (int i = head[u]; ~i; i = e[i].next) {
int v = e[i].v;
if (v == p) continue;
dfs1(u, v);
tot += num[v];
tmp = (1LL*tmp*((1LL*C(num[v], tot)*dp[v])%mod))%mod;
}
dp[u] = tmp;
num[u] = tot +;
} void dfs2(int p, int u) {
for (int i = head[u]; ~i; i = e[i].next) {
int v = e[i].v;
if (v == p) continue;
dp[v] = (1LL*(1LL*dp[u]*num[v])%mod*inv(num[u]-num[v]))%mod;
num[v] = num[u];
if (head[v] != -) dfs2(u, v);
}
} int main() {
prepare();
int T;
scanf("%d", &T);
while (T--) {
int a, b;
scanf("%d", &n);
memset(head, 0xff, sizeof (head));
idx = ;
for (int i = ; i < n; ++i) {
scanf("%d %d", &a, &b);
insert(a, b), insert(b, a);
}
dfs1(, ), dfs2(, );
int ret = ;
for (int i = ; i <= n; ++i) {
ret = (1LL*ret+(1LL*dp[i]*dp[i]%mod))%mod;
}
printf("%d\n", ret);
}
return ;
}
HDU-4662 MU Puzzle
题意:一个字符串初始化为MI,有三种操作:1:将M之后的字符串加倍或者;2:III变成U;3:UU变为空。要求判定一个字符串能否由MI变化而来。
分析:只需要把所有的字符变为 I 之后,判定 I 是否为2的幂即可。由于UU可以变为空,因此设U的个数为A,I 的个数为B,判定3A+B+6x = 2^k是否存在解。做法是两边除2然后同时对3取模。由于2的幂的3的余数只有1、2两个,因此只要不是3的倍数都行。
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std; const int N = ;
char str[N]; int main() {
int T;
scanf("%d", &T);
while (T--) {
scanf("%s", str);
int len = strlen(str);
int tot = , mnum = ;
if (!strcmp(str, "MI")) {
puts("Yes");
continue;
}
for (int i = ; i < len; ++i) {
if (str[i] == 'I') tot += ;
else if (str[i] == 'U') tot += ;
else mnum++;
}
if (mnum > || str[] != 'M') {
puts("No");
continue;
}
if ((tot & ) || (tot/) % == ) puts("No");
else puts("Yes");
}
return ;
}
2013 Multi-University Training Contest 6的更多相关文章
- Integer Partition(hdu4658)2013 Multi-University Training Contest 6 整数拆分二
Integer Partition Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) T ...
- Partition(hdu4651)2013 Multi-University Training Contest 5
Partition Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Sub ...
- ACM ICPC Central Europe Regional Contest 2013 Jagiellonian University Kraków
ACM ICPC Central Europe Regional Contest 2013 Jagiellonian University Kraków Problem A: Rubik’s Rect ...
- Partition(hdu4651)2013 Multi-University Training Contest 5----(整数拆分一)
Partition Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Sub ...
- JSU 2013 Summer Individual Ranking Contest - 5
JSU 2013 Summer Individual Ranking Contest - 5 密码:本套题选题权归JSU所有,需要密码请联系(http://blog.csdn.net/yew1eb). ...
- HDU4888 Redraw Beautiful Drawings(2014 Multi-University Training Contest 3)
Redraw Beautiful Drawings Time Limit: 3000/1500 MS (Java/Others) Memory Limit: 65536/65536 K (Jav ...
- HDU 2018 Multi-University Training Contest 3 Problem A. Ascending Rating 【单调队列优化】
任意门:http://acm.hdu.edu.cn/showproblem.php?pid=6319 Problem A. Ascending Rating Time Limit: 10000/500 ...
- 2015 Multi-University Training Contest 8 hdu 5390 tree
tree Time Limit: 8000ms Memory Limit: 262144KB This problem will be judged on HDU. Original ID: 5390 ...
- hdu 4946 2014 Multi-University Training Contest 8
Area of Mushroom Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) ...
- 2016 Multi-University Training Contest 2 D. Differencia
Differencia Time Limit: 10000/10000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Tot ...
随机推荐
- IE11下,IIS7.5不自动生成__doPostBack事件
MS在 2013/10/8 已出补丁 http://www.microsoft.com/zh-cn/download/details.aspx?id=39257 https://support.mic ...
- Linux中查找最耗性能的JAVA代码
在这里总结一下查找Linux.Java环境下最耗CPU性能的代码段的方法.基本上原理就是使用top命令查看最耗cpu的进程和线程(子进程).使用jstack把java线程堆栈给dump下来.然后,在堆 ...
- 收藏本网站兼容火狐IE
<script type="text/javascript"> function AddFavorite(sURL, sTitle) {try { window.ext ...
- [HTML]网页开发学习笔记
为了要开发一套教学使用的教师管理系统,(客户需求使用网页做教师控制端口)我便学习了一下HTML网页开发. 很不错的学习开发的网站:http://www.w3school.com.cn/index.ht ...
- android中文件操作的四种枚举
1.MODE_PRIVATE:默认操作模式,代表该文件是私有数据,只能被应用自身访问,在该模式下,写入的的内容会覆盖原文件中的内容. 2.MODE_APPEND:该模式会检查文件是否存在,存在就往文件 ...
- 发现数据库错误模式(AppScan扫描结果)
最近工作要求解决下web的项目的漏洞问题,扫描漏洞是用的AppScan工具,其中此篇文章是关于发现数据库错误模式问题的.下面就把这块东西分享出来. 原创文章,转载请注明 --------------- ...
- Mysql 升级到 5.6 后插入语句时间字段报错:Incorrect datetime value: '' for column 'createtime'
今天部署服务器项目运行,当遇见有时间数据对象的插入和更新操作的时候,就报错,如下: Caused by: com.mysql.jdbc.MysqlDataTruncation: Data trunca ...
- Android中直播视频技术探究之---视频直播服务端环境搭建(Nginx+RTMP)
一.前言 前面介绍了Android中视频直播中的一个重要类ByteBuffer,不了解的同学可以 点击查看 到这里开始,我们开始动手开发了,因为我们后续肯定是需要直播视频功能,然后把视频推流到服务端, ...
- bmp格式图片文件读取
C++读取bmp图片 #include <windows.h> #include <stdio.h> #include <stdlib.h> #include &l ...
- 改变了一下blog的主题,很开心
调整了一下博客的样式,之前一直想改变下,一直不会这次终于摸索出来一点,不过是最简单的,就是在管理里面的设置,可以定制css代码,修改修改,页面就跟着你的想法走了,有时间好好修改下,暂时这个样子,简单大 ...