2010 ACM-ICPC Multi-University Training Contest(2)——Host by BUPT 解题报告[部分]

2010 ACM-ICPC Multi-University Training Contest(2)——Host by BUPT 解题报告[部分]_第1张图片
 

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 ;
}

 





1

3

6

6

5

3

1

2

3

 

 

 

 

1

2

3

 

 

 

 

1

2

3

 

 

 

 

1

2

3

你可能感兴趣的:(test)