每到5月好像就不是那么在状态 :Worry:
分类存档:默认分类
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集训队报名须知
请认真填写好报名表并提交。并发送标题为“[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备战准备,组队练习 | |
|
集训选拔标准
以下是集训报名合格的标准,目前还没达到合格标准的同学也可以先报名,但只有达到合格标准后才能才加新手上路的选拔赛,进而成为集训队成员。以下所有成绩累加,男生达到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. 其它
包括但不局限于以下几条也可作为报名选拔的依据:
- ppmm,报名时需附上艺术照和生活照各一张
- 中学参加OI所获成绩可作为参考,但原则上仍然要达到所需分数
- 这学期开始学习C/C++/Java的大一新生因为时间相对较少,可适当降低标准
- 本科不在浙江大学,参加过ACM/ICPC并获得优异成绩的研究生新生
- 有其他特殊情况,认为自己可以不仅限于以上几组的同学