2020.06.01——习题训练4
A - Dreamoon and Ranking Collection
题意:给定长为n的数组和可以给数组加上任意数字的次数x,求这个数组从1到v最大可以连续到的数v.
解题思路:先记录原数组的数字,再从1开始遍历,看存在就不添加,然后再从得到的最后一个数开始遍历,看原数组是否还有连续数.
ac代码:
#include<iostream> #include<cmath> #include<algorithm> #include<map> using namespace std; int a[1005]; int main(){ int t,n,i,x,p; map<int,int>mp; cin>>t; while(t--){ mp.clear(); cin>>n>>x; for(i=0;i<n;i++){ cin>>a[i]; mp[a[i]]=1; } for(i=1;i<=x;i++){ if(mp[i]==1){ x++; } } p=x; for(i=x+1;;i++){ if(mp[i]==1){ p=i; } else{ break; } } cout<<p<<endl; } return 0; }
B - Dreamoon Likes Permutations
题意:给定数组,判定数组可以在不改变排列顺序的前提下被分割成两个元素连续的数组.
解题思路:先正向记录可能的分割点,即i=ma;再逆向记录可能的分割点,即ma=n-i-1;最后判断正向逆向相差为1的分割点是否都存在.
ac代码:
#include<iostream> #include<map> #include<cstring> #include<cmath> #include<algorithm> using namespace std; int a[200005],xx[200005],yy[200005]; int main(){ int t,n,i,ma,p; cin>>t; map<int,int>mp; map<int,int>x; map<int,int>y; while(t--){ cin>>n; mp.clear(); x.clear(); y.clear(); for(i=1;i<=n;i++){ cin>>a[i]; } ma=0; for(i=1;i<=n;i++){ if(mp[a[i]]){ break; } mp[a[i]]=1; ma=max(ma,a[i]); if(ma==i){//i为一个可能分割点 x[i]=1; } } ma=0; mp.clear(); for(i=n;i>=1;i--){ if(mp[a[i]]){ break; } mp[a[i]]=1; ma=max(ma,a[i]); if(ma==n-i+1){//i为一个可能分割点 y[i]=1; } } int k=0; for(i=1;i<n;i++){ if(x[i]&&y[i+1]){//正序倒序均为分割点 xx[k]=i; yy[k]=n-i; k++; } } cout<<k<<endl; for(i=0;i<k;i++){ cout<<xx[i]<<" "<<yy[i]<<endl; } } return 0; }
C - Exercising Walk
题意:给定单元格的初始点(x,y),和边界x1<=x<=x2,y1<=y<=y2,判断是否可以左右上下各移动a,b,c,d次.
解题思路:先特判只有y上下限和x上下限,再将左与右,上与下相抵消,判断其范围是否超出边界即可.
ac代码:
#include<iostream> #include<cmath> #include<algorithm> #include<map> using namespace std; int main(){ int t,a,b,c,d; long long int x,y,x1,y1,x2,y2; cin>>t; while(t--){ cin>>a>>b>>c>>d; cin>>x>>y>>x1>>y1>>x2>>y2; if(x==x1&&x==x2&&(a||b)){ cout<<"NO"<<endl; continue; } if(y==y1&&y==y2&&(c||d)){ cout<<"No"<<endl; continue; } x=x-a+b; y=y-c+d; if(x>=x1&&x<=x2&&y<=y2&&y>=y1){ cout<<"Yes"<<endl; } else{ cout<<"No"<<endl; } } return 0; }
D - Composite Coloring
题意:给定数组,将其元素分类涂色,满足:
①最终颜色的个数不会超过11。②对于gcd大于1的数字来说,颜色一样。③对于gcd等于1的数字来说,颜色一定不一样.
解题思路:1000以内的质因数个数就是11个,1000以内的数的因子里都或多或少包含着这一个或几个质因数,数组枚举遍历即可.
ac代码:
#include<iostream> #include<map> using namespace std; int a[2005]; int b[12]={0,2,3,5,7,11,13,17,19,23,29,31}; int main(){ int t,n,i,j,m; map<int,int>mp; cin>>t; while(t--){ cin>>n; mp.clear(); m=0; for(i=0;i<n;i++){ cin>>a[i]; for(j=1;j<=11;j++){ if(a[i]%b[j]==0&&mp[b[j]]){ a[i]=mp[b[j]]; break; } if(a[i]%b[j]==0){ m++; mp[b[j]]=m; a[i]=mp[b[j]]; break; } } } cout<<m<<endl; for(i=0;i<n-1;i++){ cout<<a[i]<<" "; } cout<<a[n-1]<<endl; } return 0; }
E - K-th Beautiful String
题意:求一串由2个"b"和n-2个"a"组成的,在所有可能的字典序中第k个字符串.
解题思路:找规律,第一个b在倒数第二个位置的有1个,倒数第三个b位置的有3个,倒数第四个b有4个,然后第二个从末尾开始倒序。
ac代码:
#include<iostream> #include<map> using namespace std; int main(){ long long int t,n,k,i,s,x,y; cin>>t; while(t--){ cin>>n>>k; s=0; for(i=1;;i++){ s+=i; if(s>=k){//判断第一个b是在哪个范围 s=s-i; break; } } x=n-i;//第一个b的位置 y=n-(k-s-1);//第二个b的位置 for(i=1;i<=n;i++){ if(i==x||i==y){ cout<<"b"; } else{ cout<<"a"; } } cout<<endl; } return 0; }
F - Carousel
题意:给木马动物涂色,唯一的限制是相邻的不同种动物不能为同一种颜色(这是一个环),求最少需要的颜色以及涂色方案。
解题思路:
1、所有的ai都相等,那么只需要1个颜色,全部染为1.
2、至少需要2个颜色:
①:当n为偶数,那么只需要2个颜色,染为1,2,1,2,….
②:当n为奇数,去判断环中是否有两个相邻的数字相等,
如果有:则将其假象的合并为一个数字(染成相同的颜色),这样剩下n-1项由1,2交叉循环即可。
否则需要3个颜色,染法:前n−1个数染1,2循环,最后一个数染为3。
ac代码:
#include<iostream> #include<map> #include<cstring> #include<cmath> #include<algorithm> using namespace std; long long int t[2000005],c[2000005]; int main(){ int q; cin >> q; while (q --){ int n; cin>>n; int num = 0; for (int i = 1; i <= n; ++ i){ cin>>t[i]; if (t[i] == t[1]) num ++; } if (num == n){//特判答案为1 cout << 1 << endl; for (int i=1; i<n; ++i) cout<<"1 "; cout << 1 << endl; continue; } c[1] = 0; for (int i=2; i<= n-1; ++ i) c[i] = c[i-1]^1;//0,1交替 if (n&1){//n为奇数 for (int i=2; i<=n-1; ++i){ if (t[i]==t[i-1]){//找到,使c[n-1] == c[1] for (int j=i; j<=n-1; ++j){ c[j]^= 1; } break; } } } int ans = 2; if (c[n-1]==c[1]){ c[n]=c[1]^1;//反正答案为2,即使c[n] == c[n - 1] == c[1],也为c[n]涂上不同颜色 }else { if (t[n]!= t[n-1] && t[n]!= t[1]){ ans=3;//说明所有木马属性都不同 c[n]=2; }else { if (t[n]==t[1]) c[n]=c[1];//和谁一样就涂谁的颜色 else c[n]=c[n-1]; } } cout<<ans<<endl; for (int i=1; i<n; ++i) cout<<c[i]+1<<" ";//答案要加1 cout<<c[n]+1<<endl; } return 0; }