前言
蒟蒻又来发题解了,又是烧脑写题的一天啊 QAQ
虽然当时做不出来,但是之后补题很快乐(^ - ^)!!!
A. Dense Array
题目的大致意思:对数组中相邻两个数之间添加数字,使得相邻两个数相除的结果不大于2,输出最后加入数的个数。(水题~)
解题思路:先遍历数组,找到需要进行加数的两个数。然后对大的数字进行操作,每次向上取不小于其二分之一的最小整数(ceil函数,向上取),循环操作,统计操作次数,继续遍历数组。
题解:
#include<iostream>
#include<cmath>
using namespace std;
int main()
{
int t;
cin>>t;
while(t--){
int n;
cin>>n;
int a[n];
int ans=0;
for(int i=0;i<n;i++)
cin>>a[i];
for(int i=0;i<n-1;i++){
if(max(a[i],a[i+1])/min(a[i],a[i+1])>2||max(a[i],a[i+1])/min(a[i],a[i+1])!=0){//这里的判断有点儿麻烦,需要改进
int Max=max(a[i],a[i+1]),Min=min(a[i],a[i+1]);
int t=ceil(Max*1.0/2);
while(t>Min){//循环处理最大数,直到不满足相邻两数相除商不大于2
ans++;
t=ceil(t*1.0/2);
}
}
}
cout<<ans<<endl;
}
return 0;
}
B. Balanced Remainders
题目的大致意思:给定数字个数为3的整数倍的数组,将数组内元素通过每一次指定加1的操作进行,使得最终数组内的元素除以3的余数等于0,1,2的个数相等,输出需要进行的操作最小次数。(水题~)
解题思路:先对数组进行遍历,统计出余数为0,1,2的元素个数,如果不相等,余数为0的元素多了,就将多的元素转化为余数为1的元素;余数为1的多余元素就转化为余数为2的元素;余数为2的就转化为余数为0的元素。通过循环使得最后的三者元素个数相等,最后输出操作的总次数。
#include<iostream>
#include<cmath>
using namespace std;
int main()
{
int t;
cin>>t;
while(t--){
int n;
cin>>n;
int a[n],c0=0,c1=0,c2=0,ans=0;
for(int i=0;i<n;i++){//遍历统计最初的个数
cin>>a[i];
if(a[i]%3==0)c0++;
if(a[i]%3==1)c1++;
if(a[i]%3==2)c2++;
}
while(c0!=n/3||c1!=n/3||c2!=n/3){//循环实现每个余数对应元素的最后个数都相等
if(c0>n/3){
ans+=(c0-n/3);
c1+=(c0-n/3);
c0=n/3;
}
if(c1>n/3){
ans+=(c1-n/3);
c2+=(c1-n/3);
c1=n/3;
}
if(c2>n/3){
ans+=(c2-n/3);
c0+=(c2-n/3);
c2=n/3;
}
}
cout<<ans<<endl;
}
return 0;
}
C. Sum of Cubes
题目的大致意思:判断给定的数能不能由两个数的三次方和得到。
解题思路:如果说要求两个大数的和,就属于高精度问题了,而且给定的数是10的12次方,那么一定不能用int来储存数据。由于数据很大,就只能转减法来计算,这样能够使计算过程的数据没有很大。那么数据问题解决之后就考虑实现了,从1开始遍历试验,对于给定数减去正在试验的数的三次方的差值进行二分计算比较,算出三次方能够等于差值的数,如果能够找到该数字,那么就一定能符合情况。当所有的三次方小于等于给定数的所有数字遍历完之后还是没有找到符合条件的情况时,就输出NO,找到就输出YES。
题解:
#include<iostream>
using namespace std;
typedef long long ll;
int main()
{
int t;
cin>>t;
while(t--){
ll x;
cin>>x;
bool flag=0;
for(ll i=1;i<=10000;i++){
if(i*i*i>=x)break;//试验的数要满足情况
ll res=x-i*i*i;
ll l=1,r=10000;
while(l<r){//二分查找
ll mid=(l+r)>>1;
if(mid*mid*mid>=res)r=mid;
else l=mid+1;
}
if(l*l*l==res){
flag=1;
break;
}
}
if(flag)cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
return 0;
}
D. Permutation Transformation
题目的大致意思:给定的数组元素是从1到n的数字,从给定数字数组中的最大的数字开始,将所有的数字连成树状。如果区间最大值在分界最大值左边,就连在它的左边;区间最大值在分界最大值右边,就连在它的右边。输出数字所在的数的深度,从0开始。
解题思路:用一个结构体储存数组的值和每个数的深度,对于每一层的数向下一层长可以使用递归实现,每一次对左右两个区间进行递归之后储存对应数字的层数。
题解:
#include <iostream>
#define ll long long
using namespace std;
struct node{
ll x,y;
}a[105];
void doo( ll l,ll r,ll num){
ll mx=l,i;
if(l>r)return ;
for(i=l;i<=r;i++)if(a[mx].x<a[i].x)mx=i;
a[mx].y=num;
doo(l,mx-1,num+1),doo(mx+1,r,num+1);
}
int main(){
ll t,l,r,n,i,j;
cin>>t;
while(t--){
cin>>n;
for(int i=0;i<n;i++){
cin>>a[i].x;
a[i].y=0;
}
doo(0,n-1,0);
for(int i=0;i<n;i++)
cout<<a[i].y<<" ";
cout<<endl;
}
return 0;
}
总结
能力有限,暂时只能解到这一题惹,剩余的题以后再更新(~ - ~)