The 2018 ACM-ICPC Asia Qingdao Regional Contest

 

恭喜我校某兰区域赛第一次获奖!

队友666,老师666!

 

4070     Function and Function

比赛时写得比较复杂了,比赛后得出循环只有0,1两个。那时候心态小崩。

 1 #include <cstdio>
 2 #include <cstdlib>
 3 #include <cmath>
 4 #include <cstring>
 5 #include <string>
 6 #include <ctime>
 7 #include <set>
 8 #include <map>
 9 #include <list>
10 #include <queue>
11 #include <stack>
12 #include <vector>
13 #include <bitset>
14 #include <algorithm>
15 #include <iostream>
16 using namespace std;
17 #define ll long long
18 const int maxn=1e5+10;
19 
20 int f[10]={1,0,0,0,1,0,1,0,2,1};
21 
22 int main()
23 {
24     int t,x,xx,k,i;
25     scanf("%d",&t);
26     while (t--)
27     {
28         scanf("%d%d",&x,&k);
29         for (i=1;i<=10;i++)
30         {
31             if (k==0)
32                 break;
33             if (x==0 || x==1)
34                 break;
35 
36             xx=x;
37             x=0;
38             while (xx)
39             {
40                 x+=f[xx%10];
41                 xx/=10;
42             }
43             k--;
44         }
45         if (k & 1)
46             printf("%d\n",x^1);
47         else
48             printf("%d\n",x);
49     }
50     return 0;
51 }

 

4060     Flippy Sequence

对两个二进制数异或后,找过连续1(需要修改)的区间数目

方法为:

//一个区间的结尾

a[n]=-1//

if (a[i]!=a[i+1])

  //判断区间是连续0还是连续1

  if a[i]==1

    xxx

  //一个区间的开头

  change interval_begin_index

 

分情况考虑:

3:impossible

2:6

          3*2

1:n-1

0:n*(n+1)/2

x,y,x,y

any x,y in [1,n] & x<=y

 

 

4067     Books

二分的错误性:

input:

5 1
100 3 4 5 6
output:

102

 

价钱从1~max,买到的书不一定是连续的,所以不能用二分
 
贪心:
除去必买的价格为0的书,选择前m'本,再选择之后书中价格最小的减一(刚好不能购买)。
贪心证明:
若不买前m本,假设用后面价格为x的书代替价格为y的书,x>y,那么钱足够,必须买y,矛盾。
 
 1 #include <cstdio>
 2 #include <cstdlib>
 3 #include <cmath>
 4 #include <cstring>
 5 #include <string>
 6 #include <ctime>
 7 #include <set>
 8 #include <map>
 9 #include <list>
10 #include <queue>
11 #include <stack>
12 #include <vector>
13 #include <bitset>
14 #include <algorithm>
15 #include <iostream>
16 using namespace std;
17 #define ll long long
18 const int maxn=1e5+10;
19 
20 int a[maxn];
21 
22 int main()
23 {
24     int t,n,buy,g,i,add;
25     ll sum;
26     scanf("%d",&t);
27     while (t--)
28     {
29         scanf("%d%d",&n,&buy);
30 
31         g=0;
32         for (i=1;i<=n;i++)
33         {
34             scanf("%d",&a[i]);
35             if (a[i]==0)
36                 g++;
37         }
38 
39         if (n==buy)
40         {
41             printf("Richman\n");
42             continue;
43         }
44 
45         if (g>buy)
46         {
47             printf("Impossible\n");
48             continue;
49         }
50 
51         buy-=g;
52         sum=0;
53         add=1e9;
54         for (i=1;i<=n;i++)
55             if (a[i]!=0)
56             {
57                 if (buy>0)
58                 {
59                     buy--;
60                     sum+=a[i];
61                 }
62                 else
63                     add=min(add,a[i]);
64             }
65         printf("%lld\n",sum+add-1);
66     }
67     return 0;
68 }

 

错误的二分代码:

 1 #include <cstdio>
 2 #include <cstdlib>
 3 #include <cmath>
 4 #include <cstring>
 5 #include <string>
 6 #include <ctime>
 7 #include <set>
 8 #include <map>
 9 #include <list>
10 #include <queue>
11 #include <stack>
12 #include <vector>
13 #include <bitset>
14 #include <algorithm>
15 #include <iostream>
16 using namespace std;
17 #define ll long long
18 const int maxn=1e5+10;
19 
20 int a[maxn];
21 
22 int main()
23 {
24     int t,n,buy,g,i;
25     ll l,r,m,money;
26     scanf("%d",&t);
27     while (t--)
28     {
29         scanf("%d%d",&n,&buy);
30         g=0;
31         for (i=1;i<=n;i++)
32         {
33             scanf("%d",&a[i]);
34             if (a[i]==0)
35                 g++;
36         }
37 
38         if (n==buy)
39         {
40             printf("Richman\n");
41             continue;
42         }
43 
44         if (g>buy)
45         {
46             printf("Impossible\n");
47             continue;
48         }
49         buy-=g;
50 
51         l=1,r=1e14;
52         while (l<=r)
53         {
54             m=(l+r)>>1;
55             money=m;
56             g=0;
57             for (i=1;i<=n;i++)
58                 if (a[i]!=0 && money>=a[i])
59                 {
60                     money-=a[i];
61                     g++;
62                 }
63             if (g<=buy)
64                 l=m+1;
65             else
66                 r=m-1;
67         }
68         printf("%lld\n",r);
69     }
70     return 0;
71 }
72 /*
73 8 3
74 0 1 2 3 0 0 0 0
75 
76 8 5
77 0 1 2 3 0 0 0 0
78 
79 8 6
80 0 5 4 3 2 0 0 0
81 
82 10 9
83 1000000000 1000000000 1000000000 1000000000 1000000000
84 1000000000 1000000000 1000000000 1000000000 1000000000
85 */

 

4061     Magic Multiplication

好题!

枚举a的第一位得到唯一的b,接下来依次枚举a之后的位置。

证明:

1.

一位*一位 x*y

x确定,x*y的位数可以通过第一位决定(唯一性),然后第一位或第一位和第二位决定y的值。

 

2.

a(一位,不确定)*b(多位,确定)=c(是某个字符串的前缀)

a唯一确定。

a(一位,不确定)*b‘(一位,确定)=c'(c的第一位或第一位和第二位)

唯一决定a。

 

代码就不重复写了。

 

4062     Plants vs. Zombies

二分答案

对于一个结果,分别求出每一个点需要经过的步数(>0)

对于点x(需要走的步数为c):

step1:点x-1到点x(步数+1,c -> c-1),

step2:点x->点x+1->点x->点x+1->……(步数+(c-1)*2,c-1 -> 0)。

注意,点n是例外,有时候不必走step 1。

 

另外注意:
二分的时候,总时间可能爆long long。
 
 1 #include <cstdio>
 2 #include <cstdlib>
 3 #include <cmath>
 4 #include <cstring>
 5 #include <string>
 6 #include <ctime>
 7 #include <set>
 8 #include <map>
 9 #include <list>
10 #include <queue>
11 #include <stack>
12 #include <vector>
13 #include <bitset>
14 #include <algorithm>
15 #include <iostream>
16 using namespace std;
17 #define ll long long
18 const int maxn=1e5+10;
19 
20 int a[maxn];
21 ll b[maxn];
22 
23 int main()
24 {
25     int t,n,i;
26     ll l,r,m,step,ci;
27     bool vis;
28     scanf("%d",&t);
29     while (t--)
30     {
31         scanf("%d%lld",&n,&step);
32         for (i=1;i<=n;i++)
33             scanf("%d",&a[i]);
34         l=1,r=5e16;
35         while (l<=r)
36         {
37             m=(l+r)>>1;
38             ci=0;
39             for (i=1;i<=n;i++)
40                 b[i]=m/a[i]+(m%a[i]!=0);
41 
42             b[n+1]=0;
43             vis=1;
44             for (i=1;i<=n;i++)
45             {
46                 if (i==n && b[n]<=0)
47                     break;
48                 b[i]--;
49                 ci++;
50 
51                 if (b[i]>0)
52                 {
53                     ci+=b[i]<<1;
54                     b[i+1]-=b[i];
55                 }
56                 if (ci>step)
57                 {
58                     vis=0;
59                     break;
60                 }
61             }
62             if (vis)
63                 l=m+1;
64             else
65                 r=m-1;
66         }
67         printf("%lld\n",r);
68     }
69     return 0;
70 }
71 /*
72 4 7
73 6 6 6 12
74 
75 4 8
76 3 2 3 6
77 */

 

4063     Tournament

打表找规律

 

 

 

 

 1 #include <cstdio>
 2 #include <cstdlib>
 3 #include <cmath>
 4 #include <cstring>
 5 #include <string>
 6 #include <ctime>
 7 #include <set>
 8 #include <map>
 9 #include <list>
10 #include <queue>
11 #include <stack>
12 #include <vector>
13 #include <bitset>
14 #include <algorithm>
15 #include <iostream>
16 using namespace std;
17 #define ll long long
18 const int maxn=1e3+10;
19 
20 int f[maxn][maxn];
21 
22 int main()
23 {
24     int t,n,m,i,j,k,l,x,u,v;
25     scanf("%d",&t);
26     while (t--)
27     {
28         scanf("%d%d",&n,&m);
29         if (n & 1)
30         {
31             printf("Impossible\n");
32             continue;
33         }
34         for (i=1;i<=n;i++)
35             if (i & 1)
36                 f[1][i]=i+1;
37             else
38                 f[1][i]=i-1;
39         x=1;
40         i=2,j=4;
41         while (n%j==0)
42         {
43             for (k=i+1;k<=j;k++)
44             {
45                 x++;
46                 for (u=1,v=k;u<=n;u+=j,v+=j)
47                 {
48                     f[x][u]=v;
49                     f[x][v]=u;
50                     for (l=1;l<i;l++)
51                     {
52                         f[x][f[l][u]]=f[l][v];
53                         f[x][f[l][v]]=f[l][u];
54                     }
55                 }
56                 if (x==m)
57                     break;
58             }
59             if (x==m)
60                 break;
61             i<<=1,j<<=1;
62         }
63         if (x<m)
64             printf("Impossible\n");
65         else
66             for (i=1;i<=m;i++)
67             {
68                 for (j=1;j<=n;j++)
69                 {
70                     printf("%d",f[i][j]);
71                     if (j==n)
72                         printf("\n");
73                     else
74                         printf(" ");
75                 }
76             }
77     }
78     return 0;
79 }

 

 

posted @ 2018-11-06 10:09  congmingyige  阅读(224)  评论(0编辑  收藏  举报