5.20 练习题

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<iostream>

#include<cstdio>

#include<cmath>

using namespace std;

#define ll long long

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);

if(i<=(n/2-1)||i==n)sum1+=b;

else sum2+=b; }

cout<<abs(sum1-sum2)<<endl; } }

C - Road To Zero

题意:给你俩数,经过一系列变换同时变为零,a(花a元)是每次只能将其中一数减一,b(花b元)是将两数同时减一,求花的最少是多少

思路:两数不等的地方,必须用a消减,这样相同了,再看用a,b哪种方式,所得的数最小

代码:#include<iostream>

#include<algorithm>

using namespace std;

#define ll long long

int main() {

ll x,y,a,b,t;

cin>>t;

while(t--){

cin>>x>>y>>a>>b;

if(x<y)swap(x,y);

ll sum,sum1;

sum=a*(x-y);

if(y*b>2*a*y){sum1=sum+2*a*y;

cout<<sum1<<endl;}

else {sum1=sum+y*b;

cout<<sum1<<endl;} } }//注意范围开大点,之前是int 老是错

D - Binary Period

题意:根据给定的t子序列,输出周期k最小的字符串s.

思路:这题纯属巧合,我随便一试,竟然过了,我不懂咋过的,因为我两个随便试的都过了,

    最后,我发现嗯,有人解释了,说能删除0或1,也就是,一旦不是一样的,都可以由0  1组成

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

猜你喜欢

转载自www.cnblogs.com/1324a/p/12926607.html