2010 ACM-ICPC Multi-University Training Contest(2)——Host by BUPT 解题报告[部分]
Shift Number
分析:比赛中做出最多的一道,但也确实卡了很多大牛、菜鸟。推导的过程如下图:
1 |
3 |
6 |
6 |
5 |
3 |
1 |
2 |
3 |
|
|
|
|
1 |
2 |
3 |
|
|
|
|
1 |
2 |
3 |
|
|
|
|
1 |
2 |
3 |
等价于:
1 |
3 |
6 |
6 |
5 |
3 |
1 |
1 |
1 |
1 |
|
|
|
2 |
2 |
2 |
2 |
|
|
|
3 |
3 |
3 |
3 |
发现:1111,2222,3333都是1111的倍数,于是规律就可以看出来了。
代码
#include <stdio.h>
#include <string.h>
#define LL __int64
int main()
{
LL x;
while (scanf("%I64d", &x) != EOF) {
if (!x) break;
LL k = 1, t;
while (k < x) k = k*10+1;
k /= 10;
while (x%k != 0) k /= 10;
printf("%I64d\n", x/k);
}
return 0;
}
Bag Problem
分析:背包。数据范围比较大,用set+map水过。后来birdfly出了一组很BT的数据,把我的程序给cha掉了。呜~
代码
#include <stdio.h>
#include <string.h>
#include <set>
#include <map>
using namespace std;
int main()
{
int n, m, k, i;
int gd[41];
// freopen("in.txt", "r", stdin);
set<int, greater<int> > mp, mp1;
map<int, int> bg;
while (scanf("%d%d", &n, &m) != EOF) {
scanf("%d", &k);
for (i=0; i<k; i++) {
scanf("%d", &gd[i]);
}
mp.clear();
mp1.clear();
bg.clear();
mp.insert(0);
bg[0] = 0;
mp1 = mp;
int w;
set<int, greater<int> >::iterator it;
for (i=0; i<k; i++) {
it = mp.begin();
while (it != mp.end()) {
w = *it;
if (w+gd[i] <= m && bg[w] < n) {
mp1.insert(w+gd[i]);
bg[w+gd[i]] = bg[w]+1;
}
it++;
}
mp = mp1;
}
it = mp.begin();
int max=*it;
printf("%d\n", max);
}
return 0;
}
Consumer
分析:背包。题目原型是 USACO DEC09 vidgame,不再赘述。
Counting Sequences
分析:DP+树状数组优化。刚好最近在学树状数组,不过跟DP结合来用还是第一次,当然是参考了别人的解题报告。
dp方程很明显, dp[i] = dp[i-1]+A, dp[i]:前i个元素的 Perfect Sub-sequences 的个数,A为以第i个元素为结尾的Perfect Sub-sequences
的个数。为了求 A,可以先将元素离散化,不用处理重复的情况。f[i] 就表示 以i结尾的Perfect Sub-sequences的个数,包括单独的i(求和的需要,也是不处理重复情况的原因)。
代码
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
#define NL 100001
#define MD 9901
struct Num {
int a, id;
bool operator < (const Num &x) const {
return a < x.a;
}
}ent[NL];
int b[NL], dp[NL], t[NL];
int n, d;
inline int lowbit(int x)
{
return x&(-x);
}
int sum(int x)
{
int cnt = 0;
while (x > 0) {
cnt += t[x];
x -= lowbit(x);
}
return cnt;
}
void update(int x, int c)
{
while (x <= n) {
t[x] += c;
x += lowbit(x);
}
}
int find(int x)
{
int low = 1, high = n, mid;
int ans = 0;
while (low <= high) {
mid = (low+high)>>1;
if (ent[mid].a > x) {
high = mid-1;
}else {
ans = mid;
low = mid+1;
}
}
return ans;
}
int main()
{
int i, j;
// freopen("in.txt", "r", stdin);
while (scanf("%d%d", &n, &d) != EOF) {
for (i=1; i<=n; i++) {
scanf("%d", &ent[i].a);
ent[i].id = i;
}
sort(ent+1, ent+1+n);
b[ent[1].id] = 1;
for (i=2; i<=n; i++) {
b[ent[i].id] = i;
}
dp[1] = 0;
memset(t, 0, sizeof(t));
update(b[1], 1);
for (i=2; i<=n; i++) {
int k1 = find(ent[b[i]].a+d);
int k2 = find(ent[b[i]].a-d-1);
int inc = sum(k1)-sum(k2);
inc = (inc+MD)%MD;
dp[i] = (dp[i-1]+inc)%MD;
update(b[i], inc+1);
}
printf("%d\n", dp[n]);
}
return 0;
}