Codeforces Round #180 (Div. 1)

A
假设1的个数是偶数个(设为x),那么1的个数不可能超过x个。
假设1的个数是奇数个(设为x),那么1的个数可以变为x+1个。
当然,想要1的数目变少只要不断地pop就可以了。
显然,0可以在中间随便插,所以最后只要判1的个数。

B
当且仅当我们可以找到这样一组匹配的时候,A没法超过B:
对于每个$$0 \leq i \lt n$$有$$a[i] \leq b[match[i]]$$
证明:
1、显然有此匹配时,$$\sum a_i \leq \sum b_i$$。
2、当没有这种匹配时,对于没有被匹配到的a[i],重量取个超级大的数,然后后面的重量都一样,那么A就可以超过B了。
所以只要a, b sort一下作一下判断就可以了。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <set>
#include <map>
#include <bitset>
#include <queue>
#include <stack>
#include <vector>
using namespace std;

typedef long long ll;

#define foreach(it, v) for (__typeof((v).end()) it = (v).begin(); it != (v).end(); it++)
#define rep(i, n) for (int i = 0; i < (int)(n); i++)
#define forn(i, a, b) for (int i = (int)(a); i <= (int)(b); i++)
#define clr(a, x) memset(a, x, sizeof(a))
#define all(v) (v).begin(), (v).end()
const int N = 100005;
int m, n, k;
int a[N], b[N];

int main() {
    scanf("%d%d%d", &m, &n, &k);
    rep (i, m) scanf("%d", &a[i]);
    rep (i, n) scanf("%d", &b[i]);
    sort(a, a + m);
    sort(b, b + n);
    int j = 0;
    bool flag = 0;
    rep (i, m) {
        while (j < n && b[j] < a[i]) j++;
        if (j == n) {
            flag = 1;
            break;
        }
        j++;
    }
    puts(flag ? "YES" : "NO");
}

C
构造题不懂……其实就是太弱,一直以为6 0 1 2 3 4 5这组数据是无解的,导致后面想歪了。
看了rng_58的代码茅塞顿开。
其实根本没有无解的情况
按s sort一下,然后令m = (n + 2) / 3。
第一部分(0 <= i < m):a[i] = 0, b[i] = s[i] 第二部分(m <= i < m + m):a[i] = s[i], b[i] = 0 第三部分(m + m <= i < n):a[i] = n - i - 1, b[i] = s[i] - a[i] 第一部分的用意是把a的[1,m-1]这个区间内的值空出来 第二部分的用意是把b里[s[m - 1] + 1, +oo)这个区间的值空出来 第三部分a就把第一部分的坑填了,b则保证了大于s[m - 1],并且b值严格递增。 不得不服。 D 先保证m<=n,然后让横的限制全满足,竖的限制满足超过一半即可。只需要0,1就够了。 E 坑

SRM 576

256pt
bfs

576pt

有m块长度为L的木板,这些木板放置的位置只能是(i, i+L)这个区间,其中i必须是自然数。
在x = 0.5, 1.5, … (n-1).5都有对应的水滴下落频率。
每块木板放置的高度必须互不相同,如果两块模板同时占据了某个区间,那么只有高度比较高的那块木板能接到对应点的水。
每块木板接到的水的频率之和要在[A,B]这个区间内,问有多少不同的木板放置方案。
两个方案视作不相同当且仅当,有两个木板接到的水的区间范围不一样。

f[i][j][0] 表示第i个位置前没有木板,并已经放置了j块木板的方案数
f[i][j][1] 表示第i个位置前有一块木板的末尾,并已经放置了j块木板的方案数
f[i][j][2] 表示第i个位置前有一块木板,但那不是木板的结尾,需要放置一块木板在第(i, i+L)这个位置上以盖住这块木板的伸出部分。
转移一下即可。

#include <cstdio>
#include <cstring>
#include <cctype>
#include <cstdlib>
#include <cmath>
#include <ctime>
#include <iostream>
#include <map>
#include <set>
#include <list>
#include <sstream>
#include <queue>
#include <deque>
#include <stack>
#include <vector>
#include <bitset>
#include <algorithm>
using namespace std;
#define foreach(it, v) for (typeof((v).end()) it = (v).begin(); it != (v).end(); it++)
#define clr(a, x) memset(a, x, sizeof(a))
#define rep(i, n) for (int i = 0; i < (int)(n); i++)
#define iter(v) typeof((v).end())
#define all(v) (v).begin(), (v).end()
#define DEBUG(a) cout << #a" = " << a << endl
#define DEBUGARR(a, n) rep(i, n) cout << #a"[" << i << "] = " << a[i] << endl
typedef long long ll;

const int N = 305;
const int Mod = 1000000009;
int n;
int a[N];
int sum[N];
int f[N][N][3];

void add(int &t, int x) {
	t += x;
	if (t >= Mod) t -= Mod;
}

class TheExperiment {
    public:
    int countPlacements(vector <string> intensity, int m, int L, int A, int B)  {
    	n = sum[0] = 0;
    	rep (i, intensity.size()) {
			rep (j, intensity[i].size()) {
				a[n++] = intensity[i][j] - '0';
				sum[n] = sum[n - 1] + a[n - 1];
			}
    	}
		clr(f, 0);
		f[0][0][0] = 1;
		rep (j, m + 1) {
			rep (i, n + 1) {
				int x = f[i][j][0];
				int y = f[i][j][1];
				int z = f[i][j][2];
				add(f[i + 1][j][0], (x + y) % Mod);
				int w = (x + z) % Mod;
				if (i + L <= n) {
					rep (k, L) {
						int tmp = sum[i + k + 1] - sum[i];
						if (A <= tmp && tmp <= B) {
							add(f[i + k + 1][j + 1][k + 1 == L ? 1 : 2], w);
						}
					}
				}
				for (int k = 1; k <= L; k++){
					if (i + k > n) continue;
					if (i + k - L < 0) continue;
					int tmp = sum[i + k] - sum[i];
					if (A <= tmp && tmp <= B) {
						add(f[i + k][j + 1][1], y);
					}
				}
			}
		}
		return f[n + 1][m][0];
    }


};



// Powered by FileEdit
// Powered by TZTester 1.01 [25-Feb-2003]
// Powered by CodeProcessor

900pt

一个大小为$$10^9 * W$$ 元素为$$a-z$$的字符矩阵,知道其中大小不超过$$10 * 10$$的子矩阵的元素,问生成这个矩阵的串s可能有多少种。
已知该矩阵的生成方式为:

for (int cur = 0, i = 0; i < 10000000; i++)
    for (int j = 0; j < W; j++) {
        mat[i][j] = s[cur++];
        cur %= s.size();
    }

关键是弄清什么数目比较少,像这里是子矩阵比较小。
因为这个矩阵的生成方式是线性循环的,所以先把mat[i][j]化为mat[i * W + j]。
假设我们枚举了s的size,那么首先可以做的是判断这是不是一个可行的方案。
也就是判断是否存在mat[i % s.size()] != mat[j % s.size()] && i % s.size() == j % s.size(),这个直接两两枚举子矩阵元素判断即可。
在可行的前提下,只要再算算有多少个自由元,$$ans += 26^k$$即可,计算自由元的方法同样是两两枚举子矩阵。
但是这样肯定会TLE,所以看看哪些是可以直接一并处理的。
可以发现对于一个s的size,会造成i % s.size() == j % s.size()的情况是很少的。因为子矩阵元素总共才100个,也就是一共$$C(100, 2)$$对。而上面的等式成立的条件又是i - j == k * s.size(),所以可以找出每对i - j的约数,对它们进行上面提到的暴力处理。
而剩下的部分都是不存在i % s.size() == j % s.size()的,自由元的数目都是length - 子矩阵元素个数,所以方案都是$$26^{length - n}$$,这个随着length的增长形成等比数列,求和就很简单了。

总的来说,这个问题解决的方法来源于这样一种思路:解的大部分地方都是规则的,规则的地方直接用数学方法算出来。而对于少量不规则的部分再枚举出来单独处理。
在算法的设计中,正确衡量哪些东西比较少,哪些东西比较多是非常重要的。

#include <vector>
#include <map>
#include <set>
#include <stack>
#include <bitset>
#include <algorithm>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <queue>
#include <cstring>
using namespace std;
#define clr(a,x) memset(a, x, sizeof(a))
#define foreach(it, v) for (iter(v) it = (v).begin(); it != (v).end(); it++)
#define pb push_back
#define mp make_pair
#define rep(i, n) for (int i = 0; i < (int)(n); i++)
#define iter(v) __typeof((v).end())
typedef long long ll;
typedef pair <int,int> PII;
const int N = 100;
const int Mod = 1000000009;
int n, W;
ll c[N], w[N];

int power_mod(ll a, int b) {
    if (b < 0) return 0;
	ll res = 1;
	while (b) {
		if (b & 1) res = res * a % Mod;
		a = a * a % Mod;
		b >>= 1;
	}
	return res;
}

bool check(int len) {
	rep (i, n)
		for (int j = i + 1; j < n; j++)
			if ((c[j] - c[i]) % len == 0 && w[i] != w[j])
				return 0;
	return 1;
}

int calc(int len) {
	int cnt = 0;
	rep (i, n) {
		bool flag = 1;
		rep (j, i) {
			if ((c[i] - c[j]) % len == 0) {
				flag = 0;
				break;
			}
		}
		cnt += flag;
	}
	return len - cnt;
}

void add(ll &res, ll x) {
    res += x;
    res %= Mod;
    res += Mod;
    res %= Mod;
}

int solve() {
	set <ll> s;
	rep (i, n) {
		rep (j, n) {
			if (i < j && !s.count(c[j] - c[i])) {
				for (ll k = 1; k * k <= c[j] - c[i]; k++) {
					if ((c[j] - c[i]) % k == 0) {
						s.insert(k);
						s.insert((c[j] - c[i]) / k);
					}
				}
			}
		}
	}
	ll ans = 0;
	if (W >= n) {
        ans = power_mod(26, W - n + 1);
        add(ans, -1);
        ans = ans * power_mod(25, Mod - 2) % Mod;
	}
	for (int i = 1; i < n && i <= W; i++) {
        if (check(i)) {
            add(ans, power_mod(26, calc(i)));
        }
	}
	foreach (it, s) {
		if (*it <= W && *it >= n) {
            add(ans, -power_mod(26, *it - n));
            if (check(*it)) {
                add(ans, power_mod(26, calc(*it)));
            }
		}
	}
	return ans;
}

class CharacterBoard {

public:
int countGenerators(vector <string> fragment, int W, int i0, int j0) {
	::W = W;
	n = 0;
	rep (i, fragment.size()) {
		rep (j, fragment[i].size()) {
			c[n] = (ll)(i0 + i) * W + (j0 + j);
			w[n++] = fragment[i][j] - 'a';
		}
	}
	return solve();
}




};



// Powered by FileEdit
// Powered by TZTester 1.01 [25-Feb-2003]
// Powered by CodeProcessor


// Powered by FileEdit
// Powered by TZTester 1.01 [25-Feb-2003]
// Powered by CodeProcessor

4.17

妈咪昨天去了普陀山,今日顺便来看我,一见面就嘘寒问暖,见到我有点声沙立马拉我去药店买了一“袋”药……
然后去堕落街的蛋糕店买了块散装的蛋糕坐下吃,就当是跟我庆祝生日。

原来,不知不觉,我都已经快20岁了……
18岁的生日是来浙大读预科的第二天,人生地不熟的,糊里糊涂就过去了。
说心里话,真有点羡慕小rayray。
而今年的生日,要在叶卡捷琳堡赶返杭州的路上过了 :Cry-Out: ,回到紫金港估计都晚饭时间了。
sigh,虽然略疼,但也不枉为我生命里的一个里程碑。

依稀记得,大一C语言竞赛以后MSTC的彩蛋纳新面试上,寒mm问我们集训队会很忙,怎么协调社团活动和集训的关系blablabla…
然后我和搞学长一起回答,其实集训队不是很忙的,如果不来参加活动,一定是因为他懒(然后不知道是不是特指了一下猛犸= =b)
现在看看,当时真是太年轻了。不忙,只是没有找到忙的理由。
所谓生于忧患死于安乐,当时的我,就是一个作死的家伙……
而到了今年,要去和俄国人5V5了,要去world final了,才发觉,有那么多东西,还没准备好。
我对于自己将来的计划,还没有十足的把握。
我还不够优秀
于是,我开始主动给自己压力,开始过着忙成狗的生活。真的是很用力的一个学期,这个状态就像当年准备NOI的时候一样。

仔细一想,突然觉得从小到大,我根本没变过。
无论是小学、初中、高中、还是大学,都是经过一段比较颓废的日子,然后醒悟到“还不够”,然后就玩命地用力……
典型的不见棺材不掉泪么?
其实好像也不尽然,这和我自己目标的变更也有很大关系。
刚进来浙大的时候觉得能在ACM上混一混,去一趟final,找个好点的工作就好了。
到了后来,看着碉堡的前辈们一个一个退役,自己的rating也一点点的上涨,感觉不能再这么混下去了。
大概是因为自尊心,更可能是因为好胜心,反正,现在的我很想很想成为shi哥那么强的人。
这样我才能对我的plan有十足的把握。
这回校赛shi哥来屠人,我想除了玩玩,也算是给我们这些后辈一点忠告吧。
>_<我会用力的! 最后希望ural championship别成为教练会饭桌上说的民族烈士了……

[通知]2013年浙江大学ACM-ICPC暑期集训报名

网页版:http://acm.zju.edu.cn/summer2013/
报名表:http://acm.zju.edu.cn/summer2013/applyform

规则与报名合格计分方式与去年相同,… 欢迎大家报名(@^^)/~~~
报名截止日期为第三场新手上路选拔赛前(5月25号)。



2013年浙江大学ACM-ICPC暑期集训报名须知


2013年浙江大学ACM集训队报名须知

请认真填写好报名表并提交。并发送标题为“[Summer2013报名]姓名(常用id)”的邮件到icpc@zju.edu.cn。邮件正文简要说明目前得分和报名理由。邮箱应该与你报名所使用的外网常用邮箱相同。请勿使用自动回复!

报名截止日期为第三场新手上路选拔赛前(5月25号)。

集训日程安排

起止时间1 开放对象 比赛形式 讨论地点 备注
新手上路 练习赛 4.20 – 5.5 集训报名者 Online(192) cc98/编程答疑 欢迎所有有兴趣的同学参与讨论,同时也作为新手上路的热身
选拔赛2 5.18 – 6.9 集训报名合格者 Online(192) ZOJ Forum/Summer 2013 暑期集训队成员的选拔,大多数人3要通过选拔才能参加暑期集训
暑期集训(七月)4 7.9 – 7.31 集训队成员 CC-218(192) ZOJ Forum/Summer 2013 校队成员的选拔,所有人都要通过选拔才能成为校队队员
暑期集训(八月) 8.14 至之后 校队成员 CC-218(pc^2) ZOJ Forum/Summer 2013 Regional备战准备,组队练习
  1. 具体计划可能有变动,请关注cc98/编程答疑获得最新情报。报名后的同学请养成查收邮件的好习惯,主要的内部通知将通过邮件发布。
  2. 选拔赛时间定于5.18 – 6.9的每周周六、日,一共8场比赛至少需要参加4场。选拔赛的成绩将作为集训队成员选拔的主要依据,选拔赛与练习赛无需前往现场。
  3. 去年校队成员可自愿参加新手上路,但仍需报名。
  4. 七月的暑期集训形式和往年一样,分成四组训练。7月8日或9日将召集所有集训队员开会,会议后三天左右进行第一场比赛。最后以个人成绩作为校队成员的选拔依据。
  5. 对于尚未分配宿舍的预科生和因其他原因造成集训期间住宿困难的,学校会提供租房补助帮助租房,欢迎预科生参加集训。
  6. 对报名、集训和ACM-ICPC有任何公开的疑问请到cc98/编程答疑讨论。其余与集训和非公开题目有关的任何问题请到内部论坛ZOJ Forum/Summer 2013讨论。

集训选拔标准

以下是集训报名合格的标准,目前还没达到合格标准的同学也可以先报名,但只有达到合格标准后才能才加新手上路的选拔赛,进而成为集训队成员。以下所有成绩累加,男生达到99分,女生达到66分就算合格。

最终集训对成员的规模大概在24~32人,最终校队成员的规模大概在15~18人(5~6队)。只有满足以下条件的同学才能最终入选校队:1、是浙江大学的学生,或交流时间不少于一年的交换生;2、愿意代表浙江大学参加世界总决赛;3、生于90年及以后或第一次本科入学在09年及以后。即便不满足入选校队的条件,只要愿意并有能力,也可以参加暑期集训。

暑期集训由通过新手上路选拔赛入围者自愿报名,一旦报名,原则上不允许中途退出。请本着对自己和所有人负责的态度参加暑期集训。计算机学院的同学可以用暑期集训充当短学习,其它学院的同学也可以用暑期集训作为个性课程。

1. ZOJ

狗狗40题(这里的1001-1040) 2.5分/题
Andrew Stankevich’s Contest 1.5分/题
其余ZOJ中所有题号为质数的题 1分/题
其余题目 0.3分/题

2. 校赛

特等奖 45分
一等奖 36分
二等奖 27分
三等奖 18分
与三等奖同题数 9分

3. 省赛

参加省赛的同学以现场成绩为准,未能代表浙江大学参加省赛的同学以网络同步赛的成绩为准。参加网络同步赛的同学必须独立完成,组队参加的成绩无效。

特等奖 54分
与特等奖同题数 45分
比特等奖少一题 36分
比特等奖少两题 27分
比特等奖少三题 18分
比特等奖少四题 9分

4. TopCoder

TopCoder中Algorithm的第三高rating为依据计算得到。TopCoder的rating也将作为集训队成员选拔的参考依据。

第三高rating=r max(0, (r – 1200) / 100) ^ 2 分

5. CodeForces

CodeForces中的第三高rating为依据计算得到。CodeForces的rating也将作为集训队成员选拔的参考依据。

第三高rating=r max(0, (r – 1400) / 80) ^ 2 分

6. 其它

包括但不局限于以下几条也可作为报名选拔的依据:

  1. ppmm,报名时需附上艺术照和生活照各一张
  2. 中学参加OI所获成绩可作为参考,但原则上仍然要达到所需分数
  3. 这学期开始学习C/C++/Java的大一新生因为时间相对较少,可适当降低标准
  4. 本科不在浙江大学,参加过ACM/ICPC并获得优异成绩的研究生新生
  5. 有其他特殊情况,认为自己可以不仅限于以上几组的同学