A - Phoenix and Balance
题解:有n个分别为2^1, 2^2 , 2^3…2^n的数,n为偶数,将这n个数平均分为两组,求这两组差的绝对值最小值
方法:将数2^n分给一组,第n/2到第n-1的数分给第二组,剩下的分到一组,求两组差的绝对值
2到2^n这n个数中,2^n大于剩下n-1个数的和。因此,把2^n分给一组后,一组的数就已经肯定大于二组了,所以把剩下数大的都给二组,小的都给一组
#include<bits/stdc++.h> using namespace std; int f(int n){ int i,sum=1; for(i=1;i<=n;i++) { sum*=2; } return sum; } int main() { int t,n,sum,num; cin>>t; while(t--) { sum=0; num=0; cin>>n; for(int i=n/2;i<=n-1;i++) { sum+=f(i); } for(int j=1;j<n/2;j++) { num+=f(j); } num+=f(n); cout<<abs(num-sum)<<endl; } }
B - Phoenix and Beauty
题解:给出t个测试用例,每例第一行输入n,k,第二行输入长度为n的数组,在数组中插入一些数,插入的数介于1和n之间,使所有长度为k的子阵具有相同的和
如果输入的数组中不同的数的个数大于k,那么就输出-1;
其余情况下:因为不需要使插入后的数组长度最小化,所以可以使最终长度为n*k,先找出数组中不同值的数并存储起来,然后输出这些不同的数,如果长度不足k则用1或其他任意介于1和n之间的数来补上,最后再将该长度为k的子序列循环n次
#include<bits/stdc++.h> using namespace std; //第一行应包含美丽阵列的长度m(n≤m≤104)。你不需要最小化m。 int main() { int t; cin>>t; while(t--) { int n,k; int sum=0,ct=0; cin>>n>>k; int s[n+5],b[n+5]={0},d[n+5],max=-1; for(int i=0;i<n;i++) { cin>>s[i]; } for(int i=0;i<n;i++) { if(b[s[i]]==0)//找不同值的数 { b[s[i]]=1; d[ct++]=s[i];//存储不同值的数并记录不同值的个数 } } // cout<<ct<<endl; if(ct>k)cout<<"-1"<<endl; else { cout<<n*k<<endl; for(int i=0;i<n;i++) { for(int j=0;j<ct;j++) { cout<<d[j]<<" "; } for(int j=ct;j<k;j++)cout<<"1 "; } cout<<endl; } } }
C - Road To Zero
题解:输入两个数,有两种操作,1--消耗a两数中任意一个数减少或增加1,2--消耗b使两数均减少或增加1,最终使两数均为0,不一定同时为0,求最少花费是多少
先操作1计算其中大数到较小数时的花费abs(x-y)*a,再加上操作2时两数同时减或加1的花费;与两数分别进行a操作的总花费比较,求出较小那个费用,即为答案
#include<bits/stdc++.h> using namespace std; int main() { long long t,x,y,a,b,ct; cin>>t; while(t--) { ct=0; cin>>x>>y; cin>>a>>b; long long sum=0; ct=min(x,y)*b+abs(x-y)*a; sum=(x+y)*a; cout<<min(ct,sum)<<endl; } }
D - Binary Period
题解:输入由0和1组成的子字符串t,求使循环周期最短的字符串s(t是s的子字符串,s的长度不超过2*|t|,且由0和1组成),如果可以通过删除0个或多个元素而不改变其他元素的顺序得到t,那么t也是s的子序列
根据样例和题目可以看出如果t只有0或1,则输出原输入即可,若t中既有1也有0,则输出|t|个“10“组合
#include<bits/stdc++.h> #include<string> using namespace std; int main() { int t; cin>>t; while(t--) { char s[110]; int i,j,k=0,p=0; scanf("%s",&s); int m; m=strlen(s); for(i=0;i<m;i++) { if(s[i]=='0') { k=1; } else if(s[i]=='1')p=1; } if((k==1&&p!=1)||(k!=1&&p==1))cout<<s<<endl; else if(k==1&&p==1) { for(i=0;i<m;i++) { printf("10"); } cout<<endl; } } }
E - Nastya and Rice
题解:有n颗颗粒,每颗重量在a-b和a+b之间,总重量在c-d和c+d之间,给出t个测试用例,对于满足条件的输出“Yes",否则输出“No"
合格的标准是:
c-d<=n*(a-b)<=x<=n*(a+b)<=c+d
所以当n*(a-b)>c+d||n*(a+b)<c-d时输出No
#include<bits/stdc++.h> using namespace std; int main() { int t; cin>>t; while(t--) { int n,a,b,c,d; int k=0; cin>>n>>a>>b>>c>>d; if(n*(a-b)>(c+d)||n*(a+b)<(c-d))cout<<"No"<<endl; else cout<<"Yes"<<endl; } }
F - Nastya and Door
题解:给出n个数,找出长度为k的一段数,使其中的山峰数最多,并求出这k段数的最左端的数
样例一:1 2 4 1 2 4 1 2
b[i]: 0 0 0 1 1 1 2 2
#include<bits/stdc++.h> using namespace std; //int s[10000],b[10000]=0; int main() { int t; cin>>t; while(t--) { int n,k,p=0,m=0,x=1; cin>>n>>k; int s[n+5],b[n+5]; for(int i=0;i<n;i++) { cin>>s[i]; if(i>=2&&s[i-1]>s[i-2]&&s[i-1]>s[i]) { p++;//记下山峰的数量 } b[i]=p;//记录山峰的下标 //cout<<b[i]<<endl; }
样例一:1 2 4 1 2 4 1 2
b[i]: 0 0 0 1 1 1 2 2
for(int i=0;i<n-k+1;i++) { if(m<b[i+k-1]-b[i+1])//k段中山峰的数量 1≤L≤n−k+1 { x=i+1; } m=max(m,b[i+k-1]-b[i+1]) ; } cout<<m+1<<" "<<x<<endl; } }