5/12

2016 Multi-University Training Contest 6

官方题解

打表找规律/推公式 A A Boring Question(BH)

题意:

  ,意思就是在[0,n]里选择m个数字的相邻数字二项式组合的积的总和。

思路:

想了好久,不会,但是这题有300多人过,怀疑人生。。。

打了个表:

n=0, m=2, ans=1
n=1, m=2, ans=3
n=2, m=2, ans=7
n=3, m=2, ans=15
n=4, m=2, ans=31
n=5, m=2, ans=63
n=6, m=2, ans=127
n=7, m=2, ans=900198674
n=8, m=2, ans=1590575918
n=0, m=3, ans=1
n=1, m=3, ans=4
n=2, m=3, ans=13
n=3, m=3, ans=40
n=4, m=3, ans=121
n=5, m=3, ans=364
n=6, m=3, ans=1093
n=7, m=3, ans=-457914394
n=8, m=3, ans=-624508303
n=0, m=4, ans=1
n=1, m=4, ans=5
n=2, m=4, ans=21
n=3, m=4, ans=85
n=4, m=4, ans=341
n=5, m=4, ans=1365
n=6, m=4, ans=5461
n=7, m=4, ans=-914025821
n=8, m=4, ans=-1903277640
n=0, m=5, ans=1
n=1, m=5, ans=6
n=2, m=5, ans=31
n=3, m=5, ans=156
n=4, m=5, ans=781
n=5, m=5, ans=3906
n=6, m=5, ans=19531
n=7, m=5, ans=-681221710
n=8, m=5, ans=1872878440
n=0, m=6, ans=1
n=1, m=6, ans=7
n=2, m=6, ans=43
n=3, m=6, ans=259
n=4, m=6, ans=1555
n=5, m=6, ans=9331
n=6, m=6, ans=55987
n=7, m=6, ans=-199384196
n=8, m=6, ans=638696943

按照m排序就能看出规律,想到比赛快结束的时候,最后没时间交题了,好气啊。

官方解答:

代码:

#include <bits/stdc++.h>

typedef unsigned long long ll;
const int N = 1e5 + 5;
const int MOD = 1000000007;
int fact[N]; void init_fact(int n) {
fact[0] = 1;
for (int i=1; i<=n; ++i) {
fact[i] = (ll) fact[i-1] * i % MOD;
}
} int pow_mod(int x, int n, int MOD) {
int ret = 1;
for (; n; n>>=1) {
if (n & 1) ret = (ll) ret * x % MOD;
x = (ll) x * x % MOD;
}
return ret;
} int Inv(int x) {
return pow_mod (x, MOD - 2, MOD);
} int n, m;
int tot;
int k[N], b[N]; int calc() {
int ret = 0;
int tmp = 1;
for (int i=2; i<=m; ++i) {
tmp = (ll) tmp * fact[b[i]] % MOD;
}
ret = (ll) fact[k[m]] * Inv (fact[k[1]]) % MOD * Inv (tmp) % MOD;
return ret;
} void DFS(int cur, int len, int &ans) {
if (len == m + 1) {
ans += calc ();
return ;
}
for (int i=0; i<=n; ++i) {
k[len] = i; b[len] = k[len] - k[len-1];
DFS (i, len+1, ans);
}
} int brute(int n, int m) {
int ret = 0;
for (int i=0; i<=n; ++i) {
k[1] = i;
DFS (i, 2, ret);
}
return ret;
} int solve() {
if (n == 0) return 1;
return (1 + (ll) m * (pow_mod (m, n, MOD) - 1 + MOD) % MOD * Inv (m - 1)) % MOD;
} int main() {
int T;
scanf ("%d", &T);
while (T--) {
scanf ("%d%d", &n, &m);
//printf ("%d\n", brute (n, m));
printf ("%d\n", solve ());
}
return 0;
}

容斥原理+Lucas定理 B A Simple Chess(BH)

题意:

  n*m的格子,有r个障碍物,从(1,1)出发不走到障碍物到达(n,m)的方案数。(走法是(x1,y1)->(x1+2,y1+1) or (x1+1,y1+2))

思路:

  记第一种走法的次数为b次,第二种走法的次数为c次,那么n=1+2c+b,m=1+2b+c。如果不考虑障碍物的话,答案是。那么如果会走到第i个障碍物,那么减去的是从(1,1)到第i个障碍物的位置的方案数(不走到其他的障碍物)乘以从第i个障碍物出发到(n,m)的方案数。注意(n,m)是障碍物的话,方案数直接为0。有了想法后,用代码实现,检验正确性,获得AC,瞬间的快感,这就是ACM的魅力吧。

代码:

#include <bits/stdc++.h>

typedef long long ll;
const int N = 100 + 5;
const int MOD = 110119; ll pow_mod(ll x, int n) {
ll ret = 1;
for (; n; n>>=1) {
if (n & 1) ret = ret * x % MOD;
x = x * x % MOD;
}
return ret;
} ll Inv(ll x) {
return pow_mod (x, MOD - 2);
} ll fact[MOD]; struct Point {
ll x, y;
bool operator < (const Point &rhs) const {
ll ldis = (x - 1) + (y - 1);
ll rdis = (rhs.x - 1) + (rhs.y - 1);
return ldis < rdis;
}
}p[N];
ll res[N];
ll n, m;
int r; void init_fact(int n) {
fact[0] = 1;
for (int i=1; i<n; ++i) {
fact[i] = fact[i-1] * i % MOD;
}
} ll Lucas(ll n, ll k, int p) {
ll ret = 1;
while (n && k) {
ll nn = n % p, kk = k % p;
if (nn < kk) return 0;
ret = ret * fact[nn] % p * Inv (fact[kk] * fact[nn-kk] % p) % p;
n /= p; k /= p;
}
return ret;
} bool judge_b(ll n, ll m) {
return (-n + 2 * m - 1) % 3 == 0 && (-n + 2 * m - 1) >= 0;
} bool judge_c(ll n, ll m) {
return (2 * n - m - 1) % 3 == 0 && (2 * n - m - 1) >= 0;
} ll get_b(ll n, ll m) {
return (-n + 2 * m -1) / 3;
} ll get_c(ll n, ll m) {
return (2 * n - m - 1) / 3;
} ll solve() {
//if (r > 0 && p[r-1].x == n && p[r-1].y == m) return 0;
if (!judge_b (n, m)) return 0;
if (!judge_c (n, m)) return 0;
ll b = get_b (n, m);
ll c = get_c (n, m);
ll ret = Lucas (b + c, c, MOD); std::sort (p, p+r);
memset (res, -1, sizeof (res));
for (int i=0; i<r; ++i) {
if (!judge_b (p[i].x, p[i].y)) continue;
if (!judge_c (p[i].x, p[i].y)) continue;
if (!judge_b (n-p[i].x+1, m-p[i].y+1)) continue;
if (!judge_c (n-p[i].x+1, m-p[i].y+1)) continue;
ll ib = get_b (p[i].x, p[i].y);
ll ic = get_c (p[i].x, p[i].y);
res[i] = Lucas (ib+ic, ib, MOD); for (int j=0; j<i; ++j) {
if (res[j] == -1) continue;
if (p[i].x < p[j].x || p[i].y < p[j].y) continue;
ll nn = p[i].x - p[j].x + 1;
ll mm = p[i].y - p[j].y + 1;
if (!judge_b (nn, mm)) continue;
if (!judge_c (nn, mm)) continue;
ll jb = get_b (nn, mm);
ll jc = get_c (nn, mm);
ll tmp = res[j] * Lucas (jb+jc, jb, MOD) % MOD;
res[i] = (res[i] - tmp + MOD) % MOD;
}
ll nb = get_b (n-p[i].x+1, m-p[i].y+1);
ll nc = get_c (n-p[i].x+1, m-p[i].y+1);
ret = (ret - res[i] * Lucas (nb+nc, nb, MOD) % MOD + MOD) % MOD;
}
return ret;
} int main() {
init_fact (MOD);
int cas = 0;
while (scanf ("%I64d%I64d%d", &n, &m, &r) == 3) {
bool flag = true;
for (int i=0; i<r; ++i) {
scanf ("%I64d%I64d", &p[i].x, &p[i].y);
if (p[i].x == n && p[i].y == m) flag = false;
}
if (!flag) {
printf ("Case #%d: %I64d\n", ++cas, 0LL);
continue;
}
printf ("Case #%d: %I64d\n", ++cas, solve ());
}
return 0;
}

博弈+打表找规律 C A Simple Nim(BH)

题意:

  除了经典的Nim走法,还多了可以把一堆分成三小堆的走法。

思路:

  多了一种操作没关系,根据SG定理,只要求出x的所有后继状态的SG函数,SG(x)=mex(S),分成三小堆的状态的SG值看成三个子游戏的Nim和。至于这题的做法,打表找规律即可。

代码:

#include <bits/stdc++.h>

int sg[105];

int SG(int n) {
if (n == 0) return sg[n] = 0;
if (sg[n] != -1) return sg[n];
if (n < 3) return sg[n] = n;
bool vis[1000];
memset (vis, false, sizeof (vis));
for (int i=1; i<=n; ++i) {
for (int j=i; i+j<n; ++j) {
int k = n - i - j;
//if (k < i || k < j) continue;
vis[SG (i) ^ SG (j) ^ SG (k)] = true;
}
}
for (int i=0; i<n; ++i) vis[SG (i)] = true;
int &ret = sg[n] = 0;
while (vis[ret]) ret++;
return ret;
} void f() {
memset (sg, -1, sizeof (sg));
for (int i=0; i<=100; ++i) {
printf ("sg[%d]=%d\n", i, SG (i));
}
} int main() {
//f ();
int T;
scanf ("%d", &T);
while (T--) {
int n;
scanf ("%d", &n);
long long ans = 0;
for (int i=0; i<n; ++i) {
long long x;
scanf ("%I64d", &x);
long long sg = x;
if (x % 8 == 0) sg--;
if (x % 8 == 7) sg++;
ans ^= sg;
}
puts (ans ? "First player wins." : "Second player wins.");
}
return 0;
}

01背包 H To My Girlfriend(BH)

题意:

  ,意思是有a[i],a[j],没有a[k],a[l],和为m时的组合数。

思路:

  想到简单的背包DP,dp[i][j][s1][s2]表示考虑前i个,和为j,且必选了s1个且必不选s2个的方案数。时间复杂度为

#include <bits/stdc++.h>

const int N = 1e3 + 5;
const int MOD = 1e9 +7;
int dp[N][N][3][3];
int a[N];
int n, s; void add_mod(int &a, int b) {
a += b;
if (a >= MOD) a -= MOD;
} int solve() {
memset (dp, 0, sizeof (dp));
dp[0][0][0][0] = 1;
for (int i=1; i<=n; ++i) {
for (int j=0; j<=s; ++j) {
for (int s1=0; s1<=2; ++s1) {
for (int s2=0; s2<=2; ++s2) {
add_mod (dp[i][j][s1][s2], dp[i-1][j][s1][s2]); //不选
if (j >= a[i]) add_mod (dp[i][j][s1][s2], dp[i-1][j-a[i]][s1][s2]); //选
if (j >= a[i] && s1) add_mod (dp[i][j][s1][s2], dp[i-1][j-a[i]][s1-1][s2]); //必选
if (s2) add_mod (dp[i][j][s1][s2], dp[i-1][j][s1][s2-1]); //必不选
}
}
}
}
int ret = 0;
for (int i=1; i<=s; ++i) {
add_mod (ret, dp[n][i][2][2]);
}
return (long long) ret * 4 % MOD;
} int main() {
int T;
scanf ("%d", &T);
while (T--) {
scanf ("%d%d", &n, &s);
for (int i=1; i<=n; ++i) scanf ("%d", a+i);
printf ("%d\n", solve ());
}
return 0;
}

贪心 J Windows 10(BH)

题意:

  调音量从p到q,调低的操作,连续的情况下,1,2,4。。。停顿和上升操作都会打断连续,重新从1开始,问最少几次操作。

思路:

  直观的想法就是拼命的往下降,最后微调(上升或者停顿再下降),考虑到”停顿+一格音量“可以与”上升一格“互换,那么在下降后再上升时考虑能否用停顿替代部分上升,所以要记录停顿的次数,DFS写很好。

#include <bits/stdc++.h>

typedef long long ll;

ll DFS(ll p, ll q, ll step, ll stop) {
if (p == q) return step;
int x = 0;
while (p - (1<<x) + 1 > q) x++;
if (p - (1<<x) + 1 == q) return step + x;
ll up = q - std::max (0LL, (p - (1<<x) + 1));
ll better = x + std::max (0LL, up - stop);
return std::min (better + step, DFS (p-(1<<(x-1))+1, q, step+x, stop+1));
} int main() {
int T;
scanf ("%d", &T);
while (T--) {
ll p, q;
scanf ("%I64d%I64d", &p, &q);
if (q >= p) {
printf ("%I64d\n", q - p);
} else {
printf ("%I64d\n", DFS (p, q, 0, 0));
}
}
return 0;
}

2016 Multi-University Training Contest 6的更多相关文章

  1. 2016 Al-Baath University Training Camp Contest-1

    2016 Al-Baath University Training Camp Contest-1 A题:http://codeforces.com/gym/101028/problem/A 题意:比赛 ...

  2. 2016 Al-Baath University Training Camp Contest-1 E

    Description ACM-SCPC-2017 is approaching every university is trying to do its best in order to be th ...

  3. 2016 Al-Baath University Training Camp Contest-1 A

    Description Tourist likes competitive programming and he has his own Codeforces account. He particip ...

  4. 2016 Al-Baath University Training Camp Contest-1 J

    Description X is fighting beasts in the forest, in order to have a better chance to survive he's gon ...

  5. 2016 Al-Baath University Training Camp Contest-1 I

    Description It is raining again! Youssef really forgot that there is a chance of rain in March, so h ...

  6. 2016 Al-Baath University Training Camp Contest-1 H

     Description You've possibly heard about 'The Endless River'. However, if not, we are introducing it ...

  7. 2016 Al-Baath University Training Camp Contest-1 G

    Description The forces of evil are about to disappear since our hero is now on top on the tower of e ...

  8. 2016 Al-Baath University Training Camp Contest-1 F

    Description Zaid has two words, a of length between 4 and 1000 and b of length 4 exactly. The word a ...

  9. 2016 Al-Baath University Training Camp Contest-1 D

    Description X is well known artist, no one knows the secrete behind the beautiful paintings of X exc ...

  10. 2016 Al-Baath University Training Camp Contest-1 C

    Description Rami went back from school and he had an easy homework about bitwise operations (and,or, ...

随机推荐

  1. python学习笔记-(十三)堡垒机

    1.课前准备: 本次学习堡垒机相关知识:之前,需要安装Python的paramiko模块,该模块基于SSH用于连接远程服务器并执行相关操作. 前提: python3.5程序安装到默认路径下并已添加pa ...

  2. 如何阅读Java源码 阅读java的真实体会

    刚才在论坛不经意间,看到有关源码阅读的帖子.回想自己前几年,阅读源码那种兴奋和成就感(1),不禁又有一种激动. 源码阅读,我觉得最核心有三点:技术基础+强烈的求知欲+耐心.   说到技术基础,我打个比 ...

  3. C++变参数模板和...操作符

    https://en.wikipedia.org/wiki/Variadic_template https://msdn.microsoft.com/en-us/library/dn439779.as ...

  4. arguments

    arguments 转数组 通常使用下面的方法来将 arguments 转换成数组: Array.prototype.slice.call(arguments); 还有一个更简短的写法: [].sli ...

  5. redis教程(整理中)

    一.redis简介 1.Redis:键值对类型的内存数据库:应用于高并发和实时请求的场景: 2.Redis常用数据类型: (1) string(基本数据类型)     (2)hash 注:hash中的 ...

  6. 【荐】PHP操作MongoDB GridFS 存储文件,如图片文件

    GridFS是MongoDB的一个内置功能,它提供一组文件操作的API以利用MongoDB存储文件,GridFS的基本原理是将文件保存在两个Collection中,一个保存文件索引,一个保存文件内容, ...

  7. 【总结】虚拟机VirtualBox各种使用技巧

    作为个人学习研究,VirtualBox是首选,它是Oracle下免费的.开源.跨平台的一款虚拟机软件,小巧.实用,一点也不逊于商业版的VMware Workstation. VirtualBox官网: ...

  8. 如何查看oracle 的package源码

    select text from dba_source t where t.TYPE = 'PACKAGE BODY' and name ='EMR_RECORD_INPUT' order by li ...

  9. Uva 2319

    理解:区域覆盖.假设该点在勘测半圆的边缘,求出与该点可在一个半圆的坐标范围l,r,然后,for 一次判断 #include<cstdio> #include<algorithm> ...

  10. html5页面打包成App - Android或Iphone安装程序

    下载安装前端开发工具:HBuilder 官网下载:http://www.dcloud.io/ 根据官网说明安装 * 打开登录HBuilder,把做好的H5页面通过添加app项目把H5的文件夹加入进来( ...