比赛

  题目:  http://www.lydsy.com/JudgeOnline/problem.php?id=3139

  题解:

    3$\le$N$\le$10,比较明显是一个搜索题,一开始我是直接搜了,没有记忆化,如果先枚举每一队可以的胜负平,加上合法性判断,再进行枚举,那么是可以拿到70分的,这里有一个重要的剪枝,在枚举了每一队的情况后一定要判断胜场+负场是否相等,这里有20分。。

      以下正解:

    在爆搜的时候我们每一队每一队去枚举,我们尝试着记忆化。

    首先我们发现,对于一组数据,得分序列(读入序列)的顺序和答案是无关的,那么我们记忆当还有x个队没有处理时,每一队的剩余得分为$a_{n - x + 1}$,$a_{n - x + 2}$,......,$a_{n}$ 这个状态对答案的贡献,通过对这个数组的排序,我们可以大量去重,甚至不需要加太多的优化都可以AC。

 #include <bits/stdc++.h>
#define rep(i, a, b) for (int i = a; i <= b; i++)
#define drep(i, a, b) for (int i = a; i >= b; i--)
#define REP(i, a, b) for (int i = a; i < b; i++)
#define mp make_pair
#define pb push_back
#define clr(x) memset(x, 0, sizeof(x))
#define xx first
#define yy second
using namespace std;
typedef long long i64;
typedef pair<int, int> pii;
const int inf = 0x3f3f3f3f;
const i64 INF = 0x3f3f3f3f3f3f3f3fll;
template <typename T> void Max(T &a, T b) { if (a < b) a = b; }
template <typename T> void Min(T &a, T b) { if (a > b) a = b; }
//*************************************************************** int n;
struct Conditions {
int a[];
inline long long hash() {
long long ret = ;
rep(i, , n) ret = ret * + a[i];
return ret;
}
inline void Sort() { sort(a + n - a[] + , a + + n); }
} start, bound;
map <i64, i64> M;
const int mod = 1e9 + ;
long long dfs(int step, Conditions now) {
if (now.a[] == ) return M[now.hash()];
if (now.a[n - now.a[] + ] > * (n + - step)) return -;
if (step > n) {
now.a[]--;
now.Sort();
if (M[now.hash()]) return M[now.hash()];
return M[now.hash()] = dfs(n - now.a[] + , now);
}
long long res = , tmp;
int idx = n - now.a[] + ;
if (now.a[idx] >= ) {
now.a[idx] -= ;
tmp = dfs(step + , now);
if (tmp != -) (res += tmp) %= mod;
now.a[idx] += ;
}
if (now.a[idx] >= && now.a[step] >= ) {
now.a[idx] -= , now.a[step] -= ;
tmp = dfs(step + , now);
if (tmp != -) (res += tmp) %= mod;
now.a[idx] += , now.a[step] += ;
}
if (now.a[step] >= ) {
now.a[step] -= ;
tmp = dfs(step + , now);
if (tmp != -) (res += tmp) %= mod;
now.a[idx] += ;
now.a[step] += ;
}
res = res ? res : -;
return res;
}
int main() {
scanf("%d", &n);
start.a[] = n;
rep(i, , n) scanf("%d", &start.a[i]);
start.Sort();
bound.a[] = , bound.a[n] = ; M[bound.hash()] = ;
printf("%lld\n", dfs(, start));
return ;
}

消毒

  题目: http://www.lydsy.com/JudgeOnline/problem.php?id=3140

  题解:

    a * b * c$\le$5000,所以min(a, b, c)$\le$18。

    首先如果用长度为p * q * r的立方题来框住这些点,我们可以把它变成用 1 * p * q 或者 1 * q * r 或者 p * 1 * r的立方体来覆盖,答案不会更差。

    那么我们可以用来填充的无非是上面3种的立方体来覆盖,那么我们可以枚举最小的那一维,剩下的用二分图最小点覆盖。

    我们把最小的那一维旋转到x轴上,我们二进制枚举这一维 复杂度为$2^{18}$,剩下的我们只能用 p * q * 1 或者 p * 1 * r 来覆盖剩下的点,那么我们把不能用x轴(1 * q * r)覆盖的点分别映射到y轴,z轴上去,之后二分图最小点覆盖,也就是最大匹配,记得matrix67大神证明过König定理 http://www.matrix67.com/blog/archives/116?replytocom=4432

 #include <bits/stdc++.h>
#define rep(i, a, b) for (int i = a; i <= b; i++)
#define drep(i, a, b) for (int i = a; i >= b; i--)
#define REP(i, a, b) for (int i = a; i < b; i++)
#define pb push_back
#define mp make_pair
#define clr(x) memset(x, 0, sizeof(x))
#define xx first
#define yy second
using namespace std;
typedef long long i64;
typedef pair<int, int> pii;
const int inf = 0x3f3f3f3f;
const i64 INF = 0x3f3f3f3f3f3f3f3f;
template <typename T> void Max(T &a, T b) { if (a < b) a = b; }
template <typename T> void Min(T &a, T b) { if (a > b) a = b; }
//******************************************************************** const int maxn = ; struct point {
int x, y, z; point() {}
point(int _x, int _y, int _z) :
x(_x), y(_y), z(_z) {}
} one[maxn];
int cnt_one;
struct Ed {
int u, v, nx; Ed() {}
Ed(int _u, int _v, int _nx) :
u(_u), v(_v), nx(_nx) {}
} E[maxn];
int G[maxn], edtot;
void addedge(int u, int v) {
E[++edtot] = Ed(u, v, G[u]);
G[u] = edtot;
}
int A, B, C; bool t[maxn], used[maxn]; int belong[maxn];
bool dfs(int x) {
for (int i = G[x]; i; i = E[i].nx) {
if (used[E[i].v]) continue;
used[E[i].v] = ;
if (!belong[E[i].v] || dfs(belong[E[i].v])) {
belong[E[i].v] = x;
return true;
}
}
return false;
}
int ans;
void solve() {
static int hsh[maxn]; int hsh_cnt();
rep(i, , cnt_one) hsh[hsh_cnt++] = one[i].x;
sort(hsh, hsh + hsh_cnt); hsh_cnt = unique(hsh, hsh + hsh_cnt) - hsh;
REP(s, , << hsh_cnt) {
rep(i, , A) t[i] = ;
int tmp();
REP(i, , hsh_cnt) if (s >> i & ) t[hsh[i]] = , tmp++;
edtot = ; rep(i, , B) G[i] = ;
rep(i, , cnt_one) if (!t[one[i].x]) addedge(one[i].y, one[i].z);
rep(i, , C) belong[i] = ;
rep(i, , B) {
rep(j, , C) used[j] = ;
if (dfs(i)) tmp++;
if (tmp > ans) break;
}
Min(ans, tmp);
}
} int main() {
int T; scanf("%d", &T);
while (T--) {
scanf("%d%d%d", &A, &B, &C);
cnt_one = ;
rep(i, , A) rep(j, , B) rep(k, , C) {
int id; scanf("%d", &id);
if (id == ) one[++cnt_one] = point(i, j, k);
}
if (B > A) { swap(A, B); rep(i, , cnt_one) swap(one[i].x, one[i].y); }
if (C > A) { swap(A, C); rep(i, , cnt_one) swap(one[i].x, one[i].z); }
ans = A;
solve();
printf("%d\n", ans);
}
}

旅行

  题目: http://www.lydsy.com/JudgeOnline/problem.php?id=3141

  题解:

    

数列

  题目: http://www.lydsy.com/JudgeOnline/problem.php?id=3142

  题解:

    原数列$\underbrace{ a_{1},a_{2},a_{3}......a_{k} }_{k}$

    构造数列$b_{i}=a_{i}-a_{i-1}$

    那么我们得到$\underbrace{ b_{1},b_{2},b_{3}......a_{k-1} }_{k-1}$

    我们考虑每个不同数列的不同贡献。

    贡献为:$n-b_{1}-b_{2}-b_{3}-b_{4}-b_{k-1}$

    因为$m*(k-1)>n$所以每一个数列都有如上贡献,共有$m^{k-1}$种情况

    那么求和

    n的贡献是$n*m^{k-1}$

    对于剩下的每一项,任取一项,在这一项取1时,共有$m^{k-2}$个数列,取2时,共有$m^{k-2}$个数列......

    那么对于$b_{k}$对答案的贡献是$(\sum_{i=1}^{m})*m^{k-2}$

    所以总答案为$n*m^{k-1}+(k-1)*(\sum_{i=1}^{m})*m^{k-2}$

 #include <bits/stdc++.h>
#define rep(i, a, b) for (int i = a; i <= b; i++)
#define drep(i, a, b) for (int i = a; i >= b; i++)
#define REP(i, a, b) for (int i = a; i < b; i++)
#define mp make_pair
#define pb push_back
#define xx first
#define yy second
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int inf = 0x3f3f3f3f;
const ll INT = 0x3f3f3f3f3f3f3f3fll;
template <typename T> void Max(T &a, T b) { if (a < b) a = b; }
template <typename T> void Min(T &a, T b) { if (a > b) a = b; }
//****************************************************************** ll n, m, k, p;
ll POW(ll base, ll num) {
ll ret = ;
while (num) {
if (num & ) (ret *= base) %= p;
(base *= base) %= p;
num >>= ;
}
return ret;
}
int main() {
scanf("%lld%lld%lld%lld", &n, &k, &m, &p);
ll ans1 = n % p;
(ans1 *= POW(m , k - )) %= p;
ll ans2 = (m * (m + ) / ) % p;
(ans2 *= POW(m, k - )) %= p;
(ans2 *= k - ) %= p;
printf("%lld", ((ans1 - ans2) % p + p) % p);
return ;
}

游走

  题目: http://www.lydsy.com/JudgeOnline/problem.php?id=3143

  题解:

    首先贪心,编号小的经过次数一定多,那么我们只需要求出每一条边的经过次数即可,因为是等可能的,那么这个不好求的经过求每一个点的经过次数$P_{i}$,那么每一条边$(x,y)$的经过次数$G_{i}=\frac{P_{x}}{degree_{x}}+\frac{P_{y}}{degree_{y}}$

    那么问题转化为了如何求解$P_{i}$

    我们发现$P_{i}=\sum_{\forall(x,i)}\frac{P_{x}}{degree_{x}}+\sum_{\forall(i,x)}\frac{P_{x}}{degree_{x}}$

    但是有特殊情况$P_{1}=\sum_{\forall(x,i)}\frac{P_{x}}{degree_{x}}+\sum_{\forall(i,x)}\frac{P_{x}}{degree_{x}}+1$

           $P_{n}=1$

    那么很明显了,高斯消元,有一个地方需要注意,在消元之中,$P_{n}$应该置为0,应为只要到达n是出不来的。

  $1^{-10}$才过。。。好像long double直接过的样子。。。

 #include <bits/stdc++.h>
#define rep(i, a, b) for (int i = a; i <= b; i++)
#define drep(i, a, b) for (int i = a; i >= b; i++)
#define REP(i, a, b) for (int i = a; i < b; i++)
#define mp make_pair
#define pb push_back
#define xx first
#define yy second
#define eps 1e-10
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int inf = 0x3f3f3f3f;
const ll INT = 0x3f3f3f3f3f3f3f3fll;
template <typename T> void Max(T &a, T b) { if (a < b) a = b; }
template <typename T> void Min(T &a, T b) { if (a > b) a = b; }
//****************************************************************** const int maxn = , maxm = ; double eq[maxn][maxn];
pii E[maxm]; int ed_tot;
int deg[maxn];
double A[maxm], val[maxn]; void gauss(int m, int n) {
rep(i, , n) {
if (fabs(eq[i][i]) < eps) rep(j, i, m) { if (fabs(eq[j][i]) > eps) swap(eq[i], eq[j]); break; }
rep(j, i + , n + ) eq[i][j] /= eq[i][i];
eq[i][i] = ;
rep(j, , m) if (i != j && fabs(eq[j][i]) > eps) {
double t = eq[j][i];
rep(k, i, n + ) eq[j][k] -= t * eq[i][k];
}
}
rep(i, , m) val[i] = eq[i][n + ];
} int main() {
int n, m; scanf("%d%d", &n, &m);
rep(i, , m) {
int x, y; scanf("%d%d", &x, &y);
E[++ed_tot] = mp(x, y);
deg[x]++, deg[y]++;
}
rep(i, , m) {
eq[E[i].xx][E[i].yy] = 1.0 / deg[E[i].yy];
eq[E[i].yy][E[i].xx] = 1.0 / deg[E[i].xx];
}
rep(i, , n) eq[n][i] = ;
eq[][n + ] = -;
rep(i, , n) eq[i][i] = -;
gauss(n, n);
//val[n] = 1;
rep(i, , m) {
A[i] += val[E[i].xx] / deg[E[i].xx];
A[i] += val[E[i].yy] / deg[E[i].yy];
}
sort(A + , A + + m);
double ans();
rep(i, , m) ans += (m - i + ) * A[i];
printf("%.3lf\n", ans);
return ;
}

切糕

  题目: http://www.lydsy.com/JudgeOnline/problem.php?id=3144

  题解:

    题意有点搞笑还以为是一个平面。

    实际上是对于P*Q的每一个竖列,选一个干掉就可以了。

    哈哈哈哈哈,网络流经典模型。

    注意,以下$(x,y,z)$均表示第x层y行z列。

    首先考虑没有D限制的情况,对于每一个点,对它的上一层建它的边权的点,即$(x, y, z)\to(x-1,y,z)\quad v(x,y,z)$

    这样需要多的一层,没问题吧。如果割掉一条边相对应着选了一个点那么最小割是答案对吧。。。

    

    考虑有D的情况。

    我们必须对割进行限制,怎么做呢?

    连边

    $ \forall(x,y,z) \to(x-D,Y,Z) \quad (x-D \le0)&&|Y-y|+|X-x| \le1$

    

    来举个例子,假设$D=2$,我现在选择$(4,5,6)$这个点,和选择这个点有关的边有$(7,6,6)\to(5,5,6)$和$(4, 5, 6)\to(2,6,6)$

    对$(4, 5, 6)\to(2,6,6)$连边,这样连边以后从$(4,5,6)$就无法走到$(1,6,6)$这样的点了,应为这样构不成一个割。

    那它的上限是怎么确定的呢?是$(7,6,6)\to(5,5,6)$来阻隔的,这样就不能让它选择大于D的点,否则构不成割,如图三。

    图中左边的列表示$(x,5,6)$,右边的列表示$(x,6,6)$的列。

【HNOI2013】题解 bzoj3139~bzoj3144的更多相关文章

  1. Hnoi2013题解 bzoj3139~3144

    话说好久没写题(解)了.. 先贴份题解:http://wjmzbmr.com/archives/hnoi-2013-%E9%A2%98%E8%A7%A3/(LJ神题解..Lazycal表示看不懂..) ...

  2. [HNOI2013]题解

    代码在最后 [HNOI2013]比赛 记忆化搜索 把每一位还需要多少分用\(27\)进制压进\(long\) \(long\),\(map\)记忆化一下即可 [HNOI2013]消毒 先考虑在二维平面 ...

  3. # HNOI2012 ~ HNOI2018 题解

    HNOI2012 题解 [HNOI2012]永无乡 Tag:线段树合并.启发式合并 联通块合并问题. 属于\(easy\)题,直接线段树合并 或 启发式合并即可. [HNOI2012]排队 Tag:组 ...

  4. BZOJ3144:[HNOI2013]切糕——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=3144 看着很像网络流,但是费用流貌似无法解决这个问题,其实甚至连忽略d的情况都做不到. 最小割? ...

  5. 【BZOJ3139】[HNOI2013]比赛(搜索)

    [BZOJ3139][HNOI2013]比赛(搜索) 题面 BZOJ 洛谷 题解 双倍经验

  6. 【BZOJ3144】[HNOI2013]切糕

    [BZOJ3144][HNOI2013]切糕 题面 题目描述 经过千辛万苦小 A 得到了一块切糕,切糕的形状是长方体,小 A 打算拦腰将切糕切成两半分给小 B.出于美观考虑,小 A 希望切面能尽量光滑 ...

  7. 【BZOJ3144】[Hnoi2013]切糕 最小割

    [BZOJ3144][Hnoi2013]切糕 Description Input 第一行是三个正整数P,Q,R,表示切糕的长P. 宽Q.高R.第二行有一个非负整数D,表示光滑性要求.接下来是R个P行Q ...

  8. bzoj3144 [HNOI2013]切糕(最小割)

    bzoj3144 [HNOI2013]切糕(最小割) bzoj Luogu 题面描述见上 题解时间 一开始我真就把这玩意所说的切面当成了平面来做的 事实上只是说相邻的切点高度差都不超过 $ d $ 对 ...

  9. BZOJ3144 Hnoi2013 切糕 【网络流】*

    BZOJ3144 Hnoi2013 切糕 Description Input 第一行是三个正整数P,Q,R,表示切糕的长P. 宽Q.高R.第二行有一个非负整数D,表示光滑性要求.接下来是R个P行Q列的 ...

随机推荐

  1. UIApplicationDelegate 协议 浅析

    @protocol UIApplicationDelegate<NSObject> @optional - (void)applicationDidFinishLaunching:(UIA ...

  2. Loadrunner之文件的下载(八)

    老猪提供: https://mp.weixin.qq.com/s?__biz=MzIwOTMzNDEwNw==&mid=100000013&idx=1&sn=624f5bc74 ...

  3. Android开发 R cannot be resolved to a variable问题的分析

    R文件是系统自动生成的,如果没出现的话,你的XML文件是不是有错误?是否之前修改过res文件夹下面.xml文件 R文件没有生成的情况有几种: 1.项目没有自动编译:这种时候只需要简单的编译一下工程就会 ...

  4. CodeForces 525D Arthur and Walls

    广搜.看了官方题解才会的..... 定义2*2的小矩阵,有三个是点,一个是星,这样的小矩阵被称为元素块. 首先把所有元素块压入队列,每次取出对头,检查是否还是元素块,如果是 那么将那个*改为点,否则跳 ...

  5. If only it could be all the same like we first me

    为什么 你当时对我好 Why? You nice to me at that time. 又为什么 现在变得冷淡了 Why? Now you give a cold shoulder to me. 我 ...

  6. java文件处理之压缩,分割

    http://blog.csdn.net/ycg01/article/details/1366648 java文件处理之压缩,分割 标签: javaexceptionimportnullbytefil ...

  7. SGU_390_Tickets(另类数位DP)

    Tickets Time Limit : 1000/500ms (Java/Other)   Memory Limit : 524288/262144K (Java/Other) Total Subm ...

  8. C++头文件#include<bits/stdc++.h>

    一句话的事,直截了当——#include<bits/stdc++.h>包含C++的所有头文件 参考网站(点击):http://www.tuicool.com/articles/m6neUj ...

  9. UI和UE有什么区别呢?

    UCD(以用户为中心的设计)UE(用户体验)UI(用户界面)HCI(人机交互)usability(易用性)

  10. Sql语句不等于空

    对于这种有null的我一般用这样的句子 isnull(Tag,'') <> '文章' 这样就可以搞定了不管是字符还是数字都可以用 <>