阿里第一题:
输入一个编号 n代表数中中元素个数,第二行输入若干个整数,代表数组中的元素
在一行中输出一个编号,代表在这个元素后分割可以使得两个数组的权重的乘积最大。
如果有多个最佳答案,任意输出一个即可。
输入
3
1 2 3
输出
2
思路:
两个数加起来固定,在变化过程中求乘积最大,则x+y=m,我们求 2xy=m2-x2-y2,求xy的最大值就是求x2+y2的最小值。
x2+y2=2x2-2mx+m2 ,当且仅当x=m/2的时候,x2+y2最小。
这给我们启示,我们划分数组的时候两侧元素之和越接近越相等,乘积之和就越大,这意味着sum-temp越接近temp,即sum-2*temp越接近0!
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e5+10;
int n,a[N],sum,tmp,res,gap=1e18;
signed main(){
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i],sum+=a[i];
for(int i=1;i<n;i++){
tmp+=a[i];
if(abs(sum-2*tmp)<gap) gap=abs(sum-2*tmp),res=i;
}
cout<<res<<endl;
return 0;
}
荣耀笔试第一题
// 6 3 1 14
#include<bits/stdc++.h>
using namespace std;
const int inf=99999;
int main()
{
int n,x,y;
scanf("%d,%d,%d",&n,&x,&y);
int pos=0;
int cnt=0;
int dis=x-y;
for(int i=1;i<inf;i++)
{
if(pos+x<n){
pos+=dis;
cnt++;
}
else
break;
}
int rest=n-pos;
double min1=x/5.0; //路程除以时间等于速度
int sum=5*cnt+ceil((rest/min1)); //时间向上取整
cout<<sum<<endl;
return 0;
}
// 6 3 1 14
// 10 4 1
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n,x,y;
scanf("%d,%d,%d",&n,&x,&y);
int dis=x-y;
int count=n/dis;
if(dis*(count-1)+x>n)
count--;
int rest=n-count*dis;
double min1=x/5.0;
int sum=5*count+ceil((rest/min1)); //时间向上取整
cout<<sum;
return 0;
}
荣耀笔试第三题
输入一个数字M,存在两个质数相加等于M,求所有符合这样条件的质数组,同时输出质数组中差距最小的一组输出,且输出时候两个质数中较小的一个放在前面。
思路:
两个数加起来等于M,这两个数的最大值必然不可能超过M,同时,我只需要要搜索M的一半区间即可,因为不需要重复解,且能保证找到的第一个数是小的。
one two 加起来等于M 我再代入质数判断函数中判断即可。这里质数判断函数是通过遍历输入的数字,看他是否能被其他因子整除。注意到要增加对1的判断。
事实上,判断质数,我们可以i<=num/2 就行了,因为注意到,i大于num/2之后为了乘积等于num,这个因子就小于2,没有意义了。
#include<bits/stdc++.h>
using namespace std;
bool isNum(int num){
for(int i=2;i<num;i++){
if(num%i==0){
return false;
break;
}
}
if(num==1) return false;
return true;
}
int main(){
int M; cin>>M;
vector<vector<int>>res;
for(int i=2;i<=M/2;i++){
int one=i;
int two= M-i;
if(isNum(one) && isNum(two)){
vector<int>temp;
temp.push_back(one);
temp.push_back(two);
res.push_back(temp);
}
}
int MinValue=9999999; int out1=0,out2=0; int t;
for(int i=0;i<res.size();i++){
t=res[i][1]-res[i][0];
if(t<MinValue){
out1=res[i][0]; out2=res[i][1]; MinValue=t;
}
}
if(res.size()==0)
cout<<0<<endl;
else{
cout<<out1<<' '<<out2<<endl;
}
return 0;
}
荣耀笔试第二题:
URL1:/ab/
URL2:/vjk/
类似这样的URL,我们需要合并URL1和URL2,如果URL1的尾巴和URL2的前面都有/,要去重,如果都没有,要增加,如果都是空的,返回/,反正题目会因为一些原因考虑不全面,需要把所有情况列出来,包括A空A不空等。
思路:
代码没有保存,懒得写了,核心思路就是分析,当A等于空的时候和A不空的时候来分析。当A为空的时候,判断B是不是空,是返回/ 不是返回B
当A不为空的时候,B若不空,判断A的尾巴和B的开头是不是都是/,是的话从B的1位开始走起来,当B是空,返回A。
#include<bits/stdc++.h>
using namespace std;
int main(){
vector<string>res(2);
string s;
getline(cin,s);
stringstream ss(s);
string temp;
int index=0;
while(getline(ss,temp,',')){
res[index]=temp; index++;
}
//完成输入
string one=res[0];
string two=res[1];
// 1为空的情况
if(one.size()==0){
if(two.size()==0)
cout<<'/';
if(two.size()!=0){
if(two[0]=='/')
cout<<two;
else{
string temp;
temp="/"; //试试看把这行去掉 会不会提高通过率
two=temp+two;
cout<<two;
}
}
}
//
///1不为空的情况
int size1=one.size();
if(one.size()!=0){
if(two.size()==0){
if(one[0]=='/')
cout<<one;
else
cout<<"/"+one;
}
/
if(two.size()!=0){
if(one[size1-1]=='/' && two[0]=='/'){
string temp2;
temp2=one+two.substr(1);
cout<<temp2;
}
else if(one[size1-1]!='/'&& two[0]!='/'){
string temp3;
temp3=one+'/'+two;
cout<<temp3;
}
else if(one[size1-1]=='/'|| two[0]=='/')
cout<<one+two;
}
}
}
贝壳笔试第一题:
贝壳A的第二第三题代码怎么没保存上,算了,那就看下第一题把。
第一题看起来挺简单的,输入N,M代表有N行农田,M千克肥料,拖拉机从上往下对农行施肥,每行施肥1kg,施肥到N行,掉头继续施肥,如此反复直到拖拉机把M千克的肥料用完。
要求输出一个数组,返回每一行施肥的重量!
思路:
一开始打算直接M%N取余,但是注意到第二次返回施肥的时候,最后一行是没有给他施肥的。所以并不是简单的施肥计算。思路如下
#include<bits/stdc++.h>
using namespace std;
/*int main(){
int n; cin>>n;
vector<string>s;
for(int i=0;i<=n;i++){
string temp;
getline(cin,temp);
s.push_back(temp);
}
}
*/
int main(){
int n,m;
cin>>n>>m;
int count=m/(n-1);
vector<int>res(n);
for(int i=1;i<n-1;i++)
res[i]=count;
res[n-1]=count/2;
res[0]=(count>>1)+(count&1);
int curr=0,step=1;
if(count&1){
curr=n-1;
step=-1;
}
int left=m%(n-1);
while(left-->0){
res[curr]++;
curr+=step;
}
for(int i=0;i<res.size();i++)
cout<<res[i]<<" ";
}