2018SCin tsyzDay1 模拟赛-模拟
预计得分:70+0+0+100+100+100+100=470
实际得分:70+0+0+30+100+0+40=240
第一天就被模拟虐爆qwq
T1
https://www.luogu.org/problemnew/show/P1205
因为是找最小的,所以分别把每个操作改变后的数和要求矩阵中的数比较即可。
找到合适的退出即可。
每个操作中都有一些细节,不难,慢慢推就可推出。
§ 在luogu上测的时候因为是linux系统,故用getchar崩了,noip时切忌用getchar,防止出现意外。
§ 函数也能传二维数组,只是要声明清楚第二维的范围,如void change(char s1[][10]),所以还是不传的好,防止出现意外。
code
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 6 using namespace std; 7 int n; 8 bool flag; 9 char a[15][15],b[15][15],c[15][15]; 10 void read() 11 { 12 for(int i=1;i<=n;i++) 13 for(int j=1;j<=n;j++) 14 cin>>a[i][j]; 15 for(int i=1;i<=n;i++) 16 for(int j=1;j<=n;j++) 17 cin>>b[i][j]; 18 } 19 void doit1() 20 { 21 for(int j=1;j<=n;j++) 22 for(int i=n;i>=1;i--) 23 { 24 if(a[i][j]!=b[j][n-i+1]) 25 { 26 flag=false; 27 break; 28 } 29 } 30 } 31 void doit2() 32 { 33 for(int i=n;i>=1;i--) 34 for(int j=n;j>=1;j--) 35 { 36 if(a[i][j]!=b[n-i+1][n-j+1]) 37 { 38 flag=false; 39 break; 40 } 41 } 42 } 43 void doit3() 44 { 45 for(int j=n;j>=1;j--) 46 for(int i=1;i<=n;i++) 47 { 48 if(a[i][j]!=b[n-j+1][i]) 49 { 50 flag=false; 51 break; 52 } 53 } 54 } 55 void doit51() 56 { 57 for(int j=1;j<=n;j++) 58 for(int i=n;i>=1;i--) 59 { 60 if(c[i][j]!=b[j][n-i+1]) 61 { 62 flag=false; 63 break; 64 } 65 } 66 } 67 void doit52() 68 { 69 for(int i=n;i>=1;i--) 70 for(int j=n;j>=1;j--) 71 { 72 if(c[i][j]!=b[n-i+1][n-j+1]) 73 { 74 flag=false; 75 break; 76 } 77 } 78 } 79 void doit53() 80 { 81 for(int j=n;j>=1;j--) 82 for(int i=1;i<=n;i++) 83 { 84 if(c[i][j]!=b[n-j+1][i]) 85 { 86 flag=false; 87 break; 88 } 89 } 90 } 91 int main() 92 { 93 //freopen("transform.in","r",stdin); 94 //freopen("transform.out","w",stdout); 95 scanf("%d",&n); 96 read(); 97 98 flag=true; 99 doit1(); 100 if(flag) 101 { 102 printf("1"); 103 return 0; 104 } 105 106 flag=true; 107 doit2(); 108 if(flag) 109 { 110 printf("2"); 111 return 0; 112 } 113 114 flag=true; 115 doit3(); 116 if(flag) 117 { 118 printf("3"); 119 return 0; 120 } 121 122 flag=true; 123 for(int i=1;i<=n;i++) 124 for(int j=1;j<=n;j++) 125 { 126 if(b[i][j]!=a[i][n-j+1]) 127 { 128 flag=false; 129 break; 130 } 131 } 132 if(flag) 133 { 134 printf("4"); 135 return 0; 136 } 137 138 flag=true; 139 for(int i=1;i<=n;i++) 140 for(int j=1;j<=n;j++) 141 c[i][j]=a[i][n-j+1]; 142 doit51(); 143 if(flag) 144 { 145 printf("5"); 146 return 0; 147 } 148 flag=true; 149 doit52(); 150 if(flag) 151 { 152 printf("5"); 153 return 0; 154 } 155 flag=true; 156 doit53(); 157 if(flag) 158 { 159 printf("5"); 160 return 0; 161 } 162 163 flag=true; 164 for(int i=1;i<=n;i++) 165 for(int j=1;j<=n;j++) 166 { 167 if(a[i][j]!=b[i][j]) 168 { 169 flag=false; 170 break; 171 } 172 } 173 if(flag) 174 { 175 printf("6"); 176 return 0; 177 } 178 printf("7"); 179 fclose(stdin); 180 fclose(stdout); 181 return 0; 182 }
T2
轮换的顺序是从右到左。
开始测试的时候乘积没有看懂,果断放弃这题....
T3
https://www.luogu.org/problemnew/show/P1459
这道题三月份做过,今天忘的很惨...故一定要把做过的题随时做都能对!
从这题我们可以得出,分析问题可以分类它有限的情况----
排好序后一定分为三个区间,那么错排的数只有这几种情况:
1 在区间2中出现了数字1,而数字2到了区间1
2 在区间3中出现了数字1,而数字3到了区间1
3 在区间3中出现了数字2,而数字2到了区间3
4 一个数字1跑到了区间2,同时区间2中的一个数字2跑到了区间3,区间3中的一个数字3跑到了区间1
5 一个数字1跑到了区间3,同时区间3中的一个数字3跑到了区间2,区间2中的一个数字2跑到了区间1
其中,前三种情况进行改变只需要操作1次,而后两种操作进行改变需要2次。
那么我们可以贪心地先尽量搞前三种操作,最后在解决后两种操作。
在解决前三种操作后,大体的顺序已经出来了,只剩几个毒瘤没有回家的数。实质上我们把三个数作为一组,改变每一组需要两次操作。
code
1 #include<cstdio> 2 #include<algorithm> 3 4 using namespace std; 5 int n,ans,tmp,o,p,q; 6 int a[2000]; 7 8 int main() 9 { 10 freopen("sort.in","r",stdin); 11 freopen("sort.out","w",stdout); 12 scanf("%d",&n); 13 for(int i=1;i<=n;i++) 14 { 15 scanf("%d",&a[i]); 16 if(a[i]==1) o++; 17 if(a[i]==2) p++; 18 } 19 p=p+o; 20 for(int i=1;i<=o;i++) 21 { 22 if(a[i]!=2) continue; 23 for(int j=o+1;j<=p;j++) 24 if(a[j]==1) 25 { 26 ans++; 27 swap(a[i],a[j]); 28 break; 29 } 30 } 31 for(int i=1;i<=o;i++) 32 { 33 if(a[i]!=3) continue; 34 for(int j=p+1;j<=n;j++) 35 if(a[j]==1) 36 { 37 ans++; 38 swap(a[i],a[j]); 39 break; 40 } 41 } 42 for(int i=o+1;i<=p;i++) 43 { 44 if(a[i]!=3) continue; 45 for(int j=p+1;j<=n;j++) 46 if(a[j]==2) 47 { 48 ans++; 49 swap(a[i],a[j]); 50 break; 51 } 52 } 53 for(int i=1;i<=o;i++) if(a[i]!=1) tmp++; 54 for(int i=o+1;i<=p;i++) if(a[i]!=2) tmp++; 55 for(int i=p+1;i<=n;i++) if(a[i]!=3) tmp++; 56 ans+=tmp*2/3; 57 printf("%d",ans); 58 fclose(stdin); 59 fclose(stdout); 60 return 0; 61 }
§ o,p是记录为1的数有几个、为2的数有几个的变量,实际应用时我们却把它看成了区间上的点。因此使用时先让p+=o;
§ 进行前三次操作时,找到一个就break即可。
T4
极水。但是没开long long 。。。。。。
没开long long。。。。。
long long。。。。。。
code
1 #include<cstdio> 2 #include<algorithm> 3 4 using namespace std; 5 6 long long n,ans; 7 long long a[250000]; 8 int main() 9 { 10 freopen("simple.in","r",stdin); 11 freopen("simple.out","w",stdout); 12 scanf("%d",&n); 13 for(int i=1;i<=2*n;i++) 14 scanf("%lld",&a[i]); 15 sort(a+1,a+2*n+1); 16 for(int i=1;i<=2*n;i+=2) 17 ans+=a[i]; 18 printf("%lld",ans); 19 fclose(stdin); 20 fclose(stdout); 21 return 0; 22 }
T5
做的第一题,极水,但要考虑交20元时,有找3个5元或1个5元1个10元的情况。
code
1 #include<cstdio> 2 #include<algorithm> 3 4 using namespace std; 5 6 int n; 7 int t1,t2; 8 bool flag; 9 10 int main() 11 { 12 freopen("book.in","r",stdin); 13 freopen("book.out","w",stdout); 14 scanf("%d",&n); 15 flag=true; 16 for(int i=1;i<=n;i++) 17 { 18 int x=0; 19 scanf("%d",&x); 20 if(flag) 21 { 22 if(x==5) t1++; 23 if(x==10) 24 if(t1) t2++,t1--; 25 else flag=false; 26 if(x==20) 27 if(t1&&t2) t2--,t1--; 28 else if(t1>=3) t1-=3; 29 else flag=false; 30 } 31 } 32 if(flag) printf("YES"); 33 else printf("NO"); 34 fclose(stdin); 35 fclose(stdout); 36 return 0; 37 }
T6
没用到hash表/map,用的结构体。思路对,但是实现复杂,所以错了。而且空间开小了。
code
1 #include<cstdio> 2 #include<algorithm> 3 4 using namespace std; 5 int n,tot,ans=0x3f3f3f3f,tmp,f; 6 struct node{ 7 int val;//num没有必要 8 bool flag; 9 }a[700000]; 10 //开2倍 11 bool cmp(node p,node q) 12 { 13 return p.val<q.val; 14 } 15 16 int main() 17 { 18 freopen("card.in","r",stdin); 19 freopen("card.out","w",stdout); 20 scanf("%d",&n); 21 for(int i=1;i<=n;i++) 22 { 23 int ai=0,bi=0; 24 scanf("%d%d",&ai,&bi); 25 if(ai==bi) 26 { 27 a[++tot].val=ai,a[tot].flag=0; 28 } 29 else a[++tot].val=ai,a[tot].flag=0,a[++tot].val=bi,a[tot].flag=1; 30 } 31 sort(a+1,a+tot+1,cmp); 32 /* for(int i=1;i<=tot;i++) printf("%d ",a[i].val);printf("\n"); 33 for(int i=1;i<=tot;i++) printf("%d ",a[i].num); */ 34 for(int i=1;i<=tot;i++) 35 { 36 tmp++; 37 if(a[i].flag==0) f++;//两个量每次先记录。 38 if(a[i].val!=a[i+1].val) 39 { 40 if(tmp>=(n+1)/2) 41 { 42 int d=((n+1)/2-f);//减去正面的,就是需要翻的。 43 if(d<0) d=0; 44 ans=min(ans,d); 45 } 46 tmp=0,f=0; 47 } 48 } 49 if(ans==0x3f3f3f3f) 50 { 51 printf("Impossible"); 52 return 0; 53 } 54 printf("%d",ans); 55 fclose(stdin); 56 fclose(stdout); 57 return 0; 58 }
T7
我4月份的时候写了这题的题解!!!!
https://www.luogu.org/problemnew/solution/P3056
-------然而还是忘了。
code
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<stack> 5 6 using namespace std; 7 8 int len,l,r,ans; 9 char ch[200000]; 10 stack<char>s; 11 12 int main() 13 { 14 freopen("shower.in","r",stdin); 15 freopen("shower.out","w",stdout); 16 scanf("%s",ch+1); 17 int len=strlen(ch+1); 18 for(int i=1;i<=len;i++) 19 { 20 if(ch[i]=='(') s.push(ch[i]); 21 if(ch[i]==')') 22 { 23 if(!s.empty()) 24 s.pop(); 25 else s.push('('),r++; 26 } 27 } 28 ans=r+s.size()/2; 29 printf("%d",ans); 30 fclose(stdin); 31 fclose(stdout); 32 return 0; 33 }