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 #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。
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 }