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 ...
随机推荐
- JVM学习笔记(二)------Java代码编译和执行的整个过程【转】
转自:http://blog.csdn.net/cutesource/article/details/5904542 版权声明:本文为博主原创文章,未经博主允许不得转载. Java代码编译是由Java ...
- Centos修改镜像为国内的163源
一.yum 简介 yum,是Yellow dog Updater, Modified 的简称,是杜克大学为了提高RPM 软件包安装性而开发的一种软件包管理器.起初是由yellow dog 这一发 ...
- golang的helloworld
新建源码文件hello.go mkdir -p /work/goTest/ cd /work/goTest/ vim hello.go 编码hello.go文件: package main impor ...
- 12、Jsp加强/自定义标签/JavaBean
1 Jsp加强回顾 Jsp加强 1)Jsp的9大内置对象 request HttpServletRequet response HttpServletResponse config ...
- Linux字符串替换一例:根据IP地址获取指定内容
需求:使用脚本获取到本机IP地址,需要添加iptables规则,需生成网段地址 源格式:获取IP地址为10.10.10.221 目标格式:10.10.10.0 # 方法1 [hadoop@localh ...
- HDU 5898:odd-even number(数位DP)
http://acm.hdu.edu.cn/showproblem.php?pid=5898 题意:给出一个区间[l, r],问其中数位中连续的奇数长度为偶数并且连续的偶数长度为奇数的个数.(1< ...
- USB wifi调试笔记
本文以realtek 8192CU WiFi模块为例,介绍USB wifi在Jelly Bean 4.1的调试笔记. 1.WIFI打不开现象概述 WiFi打不开是指您在UI的settings下选中Wi ...
- 3G中的A-GPS移动定位技术
位置业务(LBS,Location Based Service)是指移动网络通过特定的定位技术来获取移动终端的位置信息,从而为终端用户提供附加服务的一种增值业务,可广泛应用于紧急救援.导航追踪.运输调 ...
- Java学习之路(三)
1:面向对象
- 理解mipi协议
完成mipi信号通道分配后,需要生成与物理层对接的时序.同步信号: MIPI规定,传输过程中,包内是200mV.包间以及包启动和包结束时是1.2V,两种不同的电压摆幅,需要两组不同的LVDS驱动电路在 ...