A - Phoenix and Balance
题意:给你一个n(n为偶数),将从2^1到2^n平均分为两份,是差的绝对值最小
思路:1.错误思路:(这题做过)我最开始我想将首尾相加,在分一半;
代码:
#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
#define ll long long
#define N 10000
ll a[N];
ll qpower(int a,int b){
ll ans=1;
while(b){
if(b&1) ans*=a;
a=a*a;
b/=2;
}
return ans;
}
int main(){
int t;
cin>>t;
while(t--){
int n;
cin>>n;
ll sum1=0,sum2=0;
for(int i=1;i<=n;i++){
ll b=qpower(2,i);
a[i]=b;
}
if(n>2){
for(int i=1,j=n;i<=n/2;i++,j--){
if(i<=n/4)sum1+=a[i]+a[j];
else sum2+=a[i]+a[j];
}
cout<<abs(sum1-sum2)<<endl;
}
else cout<<"2"<<endl;
}
}
显然错了
正解:看了人家的才知道:等比数列最后一项,大于前边所有项的和,因为又是均分,所以将最后一项和前面n/2-1项放一起即可
ac代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
int main()
{
string s;
int t;
cin>>t;
while(t--){
cin>>s;
int c=1;
ll n=s.length();
for(int i=0;i<n-1;i++){
if(s[i]!=s[i+1])
c=0;
}
if(c==1)cout<<s<<endl;
else {
for(int i=0;i<n;i++)
cout<<"01";//cout<<"10"也对
cout<<endl;
}
}
}
E - Nastya and Rice
题意:这题简单,就是给你n,a,b,c,d五个数,为你是否有n*[a-b~a+b]=[c-d~c+d]存在
思路:正难则反,求不满足条件,在看满足条件
代码:
#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
#define ll long long
int main(){
int t;
cin>>t;
while(t--){
int n,a,b,c,d;
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中山峰数最多,并求最多的山峰数
思路:实话说,这题我不会,看了别人的,自己改的,自己用的前缀和,但有部分不懂
#include <bits/stdc++.h>
using namespace std;
int main()
{
int t,n,k;
cin>>t;
while(t--){
cin>>n>>k;
int a[n+1],p[n+k+2]={0},maxx=0,r=1;
for(int i=1;i<=n;i++){
cin>>a[i];
if(i>=3&&a[i-1]>a[i-2]&&a[i-1]>a[i]){
p[i]=1;}
p[i]+=p[i-1];
}
for(int i=1;i+k-1<=n;i++)
{
if(maxx<p[i+k-1]-p[i+1])//找出k段中山峰所在位置
{
r=i;
}
maxx=max(maxx,p[i+k-1]-p[i+1]);//为啥减的是(i+1)??,不用过不去
}
cout<<maxx+1<<" "<<r<<endl;
}
return 0;
}
B - Phoenix and Beauty
题意
思路:这题我也不会。看了别人的
//方法是通过在每个数的前后补上相应不重复的数,因此发现规律只要找出没出现过的数,和原有的数一起存入集合,再循环输出
//eg: 5 4
// 2 1 2 4 1
//12341234123412341234
/#include<bits/stdc++.h>
#define ll long long
using namespace std;
int main( )
{
int t,n,k;
cin>>t;
for(int i=0; i<t; i++)
{
int n,k;
cin>>n>>k;
int a[n];
set<int>aa;
int b[105]={0};
for(int j=0;j<n;j++)
{
cin>>a[j];
aa.insert(a[j]);//存放出现过的数
b[a[j]]=1;//记录已出现过的数
}
if(aa.size()>k)//数的种类大于周期数,无法成立
{
cout<<"-1"<<endl;
}
else//如果数的种类小于周期数,少了几种数补几种数,补的数不能和a[j]中标记的数重复
{
int s=k-aa.size();//要补s个数
for(int j=1,kk=0;kk<s;j++)
{
if(b[j]==0)//要补几个数就再增加标记几个数
{
b[j]=1;
aa.insert(j);
kk++;
}
}
cout<<n*k<<endl;
for(int j=0;j<n;j++)//循环输出集合aa中的数即可
{
for(auto it=aa.begin();it!=aa.end();it++)
{
cout<<*it<<" ";
}
}
cout<<endl;
}
}
return 0;
}
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e4 + 10;
int a[maxn],b[maxn];
bool vis[maxn]; // cnt < k 时查找不同的数
int t,n,k;
int main(void) {
scanf("%d",&t);
while(t --) {
// 初始化
set<int>sets;
memset(vis,0,sizeof(vis));
scanf("%d%d",&n,&k);
for(int i = 1; i <= n; i ++) {
scanf("%d",&a[i]);
sets.insert(a[i]);
}
if(sets.size() > k) {
puts("-1");
continue;
}
printf("%d\n", n * k);
int cnt = 0;
// 遍历所有的不同的数
for(set<int>::iterator it = sets.begin(); it != sets.end(); it ++) {
b[++ cnt] = *it;
vis[*it] = true;
}
// cnt == k 时直接 n 个 k 即可
if(sets.size() == k) {
for(int i = 1; i <= n; i ++) {
for(int j = 1; j <= k; j ++) {
printf("%d ",b[j]);
}
}
} else {
// cnt < k 时补足 k 个
int num = sets.size();
for(int i = 1; i <= n; i ++) {
if(!vis[i]) b[++ cnt] = i,num ++;
if(num == k) break;
}
for(int i = 1; i <= n; i ++) {
for(int j = 1; j <= k; j ++) {
printf("%d ",b[j]);
}
}
}
puts("");
}
return 0;
}