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. Java的发展历程

    Java的发展历程充满了传奇色彩. 最初,Java是由Sun公司的一个研究小组开发出来的, 该小组起先的目标是想用软件实现对家用电器进行集成控制的小型控制装置. 开始,准备采用C++,但C++太复杂, ...

  2. 从yield关键字看IEnumerable和Collection的区别

    C#的yield关键字由来以久,如果我没有记错的话,应该是在C# 2.0中被引入的.相信大家此关键字的用法已经了然于胸,很多人也了解yield背后的“延迟赋值”机制.但是即使你知道这个机制,你也很容易 ...

  3. thinkphp 模型、控制器、视图

    控制器里面调用模型 echo D('Goods')->index(); 调用GoodsModel下index 控制器里面调用其他控制器 echo A('Goods')->index(); ...

  4. 【09-03】java泛型学习笔记

    静态方法的泛型 /** * @description 静态方法的泛型无法使用类定义的泛型,因为类在实例化时才确定具体的泛型类,因此静态方法要使用泛型需要使用泛型方法的方式 */ public clas ...

  5. Html限制input输入框只能输入数字

    限制输入框只能输入数字, onafterpaste防止用户从其它地方copy内容粘贴到输入框: <input type="text" onkeyup="this.v ...

  6. mysql 主从master-slave同步复制 配置,为读写分离准备

    1.为方便,我在一个windows下安装两个mysql实例,端口分别是 3306.3307 打开 my.ini 或 my-default.ini 文件 配置 basedir datadir 和port ...

  7. Daily Scrum Meeting ——ThirdDay

    一.Daily Scrum Meeting照片 二.Burndown Chart 三.项目进展 1.完成了github上的文档整理 Transcend/ActivityHelper 2.主界面侧滑框的 ...

  8. java基础知识(二)字符串处理

    字符串是程序开发中使用最为频繁,因此为了工作的高效和作为一名想进阶的程序员,了解并掌握字符串的处理显得尤为重要.java为我们提供了String.StringBuffer.StringBuilde三个 ...

  9. git 教程(14)--解决冲突

    人生不如意之事十之八九,合并分支往往也不是一帆风顺的. 准备新的feature1分支,继续我们的新分支开发:

  10. Java 网络编程之 Socket

    ========================UDP============================= UDP---用户数据报协议,是一个简单的面向数据报的运输层协议. UDP不提供可靠性, ...