精华 【已更新视频题解】360春招&实习生招聘3.18在线编程题解
发布于 2017-03-18 21:11 12242 次浏览 1 赞 最后一次编辑是 2017-03-28 13:44 来自 笔试面试  

讲师简介


纪磊



网名啊哈磊。毕业于武汉大学计算机学院;

曾在MSRA(微软亚洲研究院)机器学习组从事搜索引擎方面的研究;

发表国际会议论文一篇(IEEE);

全国青少年信息学奥林匹克金牌教练,曾培养了数名NOI/IOI选手

保送进MIT、清华、浙大、交大、复旦和华科等高校;

多次为ACM/ICPC亚洲赛区比赛命题;

出版畅销书《啊哈C!思考快你一步 》和《啊哈!算法》并被引进到港澳台;

2013年度51cto最受读者喜爱 的IT图书作者奖,当当网2014年度计算机和互联网热门作者第一名。 


求职360的同学可以加入奇虎360的交流群:436627572 ,供大家在此交流后续面试及职位信息。


以下为原题链接(题中包含文字题解)及视频题解


跑步:

http://exercise.acmcoder.com/online/online_judge_ques?ques_id=3861&konwledgeId=42





剪气球串:

http://exercise.acmcoder.com/online/online_judge_ques?ques_id=3862&konwledgeId=42





分金子:

http://exercise.acmcoder.com/online/online_judge_ques?ques_id=3863&konwledgeId=42





跑步:

简单数学题,直接用三角函数计算坐标。

示例代码:

#include <bits/stdc++.h>
#define maxn 100009
using namespace std;
const double PI = acos(-1.0);
int main(){
    int L,R;
    scanf("%d%d", &L, &R);
    double theta = 1.0 * L / R;
    printf("%.3f %.3f\n", R * cos(-theta), R * sin(-theta));
    printf("%.3f %.3f\n", R * cos(theta), R * sin(theta));
    return 0;
}


剪气球串:

动态规划,考虑前i个有多少种剪法,枚举最后剪的一段转移。

示例代码:

#include <bits/stdc++.h>
#define maxn 100009
using namespace std;
int n;
int a[maxn], dp[maxn];
int cnt[11];
const int MOD = 1e9 + 7;
int main(){
    scanf("%d", &n);
    for(int i = 1; i <= n; i++){
        scanf("%d", &a[i]);
    }
    dp[0] = 1;
    for(int i = 1; i <= n; i++){
        memset(cnt, 0 ,sizeof(cnt));
        for(int j = 0; j < i; j++){
            cnt[a[i - j]]++;
            if(cnt[a[i - j]] > 1)
                break;
            dp[i] = (dp[i] + dp[i - j - 1]) % MOD;
        }
    }
    printf("%d\n", dp[n]);
    return 0;
}


分金子:

博弈问题,用区间dp求解,转移考虑取最左边还是最右边,然后规约成一个子博弈问题。

示例代码:

#include <cstdio>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <map>
#include <string>
#include <stack>
#include <cctype>
#include <vector>
#include <queue>
#include <set>
#include <utility>
#include <cassert>
#include <numeric>
#include <sstream>
using namespace std;
#define Online_Judge
#define outstars cout << "***********************" << endl;
#define clr(a,b) memset(a,b,sizeof(a))
#define lson l , mid  , rt << 1
#define rson mid + 1 , r , rt << 1 | 1
#define mk make_pair

const int MAXN = 1000 + 50;
const int MAXS = 10000 + 50;
const int sigma_size = 26;
const long long LLMAX = 0x7fffffffffffffffLL;
const long long LLMIN = 0x8000000000000000LL;
const int INF = 0x7fffffff;
const int IMIN = 0x80000000;
const int inf = 1 << 30;
#define eps 1e-10
const long long MOD = 1000000000 + 7;
const int mod = 10007;
typedef long long LL;
const double PI = acos(-1.0);
typedef double D;
typedef pair<int , int> pii;
typedef vector<int> vec;
typedef vector<vec> mat;
typedef vector<string> vs;

#define Bug(s) cout << "s = " << s << endl;
///#pragma comment(linker, "/STACK:102400000,102400000")

#define MAX ((long long)1<<61)
set <int> point;
vector <int> hit;
set <int> pocket;
int dp[520][520];
int n;
int sum[520];
int a[520];
int main(int argc, char* argv[])
{
//    freopen("input.txt" , "r" , stdin);
//    freopen("output.txt" , "w" , stdout);
    int t;
    cin >> t;
    for(int kase = 1 ; kase <= t ; kase++)
    {
        scanf("%d" ,&n);
        for(int i= 1 ; i <= n ;i ++)
        {
            scanf("%d" , &a[i]);
        }
        memset(sum , 0 , sizeof(sum));
        sum[0] = 0;
        for(int i = 1 ; i <= n ; i++)
        {
            sum[i] = sum[i - 1] + a[i];
        }
        memset(dp , 0 , sizeof(dp));
        for(int l = 0 ; l < n ; l++)
        {
            for(int i = 1 ; i <= n - l ; i++)
            {
                dp[i][i + l] = max(sum[i + l - 1] - sum[i - 1] - dp[i][i + l - 1] + a[i + l], sum[i + l] - sum[i] - dp[i + 1][i + l] + a[i]);
            }
        }
        printf("Case #%d: %d %d\n" ,kase  , dp[1][n] , sum[n] - dp[1][n]);
    }
 return 0;
}
/*
6
4 7 2 9 5 2
*/


以上思路供同学们参考,也希望同学能分享自己的经验


51 条回复

继续努力!!!

2017-03-18 21:11

Java版本呢?

2017-03-18 21:13

考懵逼了

2017-03-18 21:14
1

分金子题解错了吧,哪来那么多字符串操作?

2017-03-18 21:15
8

请问能不能公布测试样例,尤其第一题,我想知道自己的代码错在哪里

2017-03-18 21:15
3

只怪自己不努力

2017-03-18 21:15

懵逼。。  同求第一个题的测试案例,不知道10%错哪了 

2017-03-18 21:16

第一题搞了好久 结果楼主几行代码就搞定了。。。。

2017-03-18 21:17

我差,一共三题?我以为两题呢,可以去哪再A一次,第二题写错了一点,差一点没改出来

2017-03-18 21:17

说好的分金子呢

2017-03-18 21:18

加油

2017-03-18 21:18

第二题的题解这复杂度这么大!!!

2017-03-18 21:20

第二题这解法能保证子串不同?还是我题目理解错了?

2017-03-18 21:20
1

public class Main {


public static void main(String[] args) {

// TODO Auto-generated method stub

Scanner sc=new Scanner(System.in);

while(sc.hasNext()){

double L=sc.nextDouble();

double R = sc.nextDouble();

double z;

z=Math.PI*2*R;

double Yu=L%z;

double x = Yu*2*Math.PI/z;

double reslutnx = R*Math.cos(x);

double reslutny = R*Math.sin(x);


double reslutsx = R*Math.cos(x);

double reslutsy = -R*Math.sin(x);

System.out.print(String.format("%.3f", reslutnx));System.out.print(" ");

System.out.println(String.format("%.3f", reslutny));

System.out.print(String.format("%.3f", reslutsx));System.out.print(" ");

System.out.println(String.format("%.3f", reslutsy));

}

}


}


2017-03-18 21:21
1

求第一题的测试用例!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

2017-03-18 21:21
3

mark

2017-03-18 21:21

真的考懵逼了

2017-03-18 21:24

第三题分金子不是dp好吧,统计奇数位和偶数位的金子和,再看n是否为偶数就行了。

2017-03-18 21:24

求问,没有ac是否有分

2017-03-18 21:24
fwm94 回复 acmcodercc1MrBLZ

第二题j的那层循环最多跑10次。

2017-03-18 21:27
小码快跑 回复 蜗牛侠

是按每个数组通过给分的,70%通过率就会得到题目相应总分的70%分数

2017-03-18 21:27
acmcoder2ctwnChP 回复 coder_JEJPYETG

你这是贪心算法,不对的,并不是每次都选择首尾中较大的那一个,最终就能拿到最多

2017-03-18 21:28

第二题可以做到准确O(n),代码如下

#include <map>
#include <set>
#include <stack>
#include <queue>
#include <cmath>
#include <ctime>
#include <vector>
#include <cstdio>
#include <cctype>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
#define INF 0x3f3f3f3f
#define inf -0x3f3f3f3f
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define mem0(a) memset(a,0,sizeof(a))
#define mem1(a) memset(a,-1,sizeof(a))
#define mem(a, b) memset(a, b, sizeof(a))
#define MP(x,y) make_pair(x,y)
typedef long long ll;
void fre() { freopen("input.in", "r", stdin); freopen("output.out", "w", stdout); }
template <class T1, class T2>inline void gmax(T1 &a, T2 b) { if (b>a)a = b; }
template <class T1, class T2>inline void gmin(T1 &a, T2 b) { if (b<a)a = b; }
const int N=1e5+100;
int pre[100];
int sum[N],a[N],dp[N];
const int MOD=1000000007;

int main(){
    int n;
    while(scanf("%d",&n)!=EOF){
        for(int i=1;i<=n;i++)
            scanf("%d",&a[i]);
        for(int i=0;i<=9;i++)
            pre[i]=0;
        int ed = 0;
        dp[1]=1,sum[1]=1;
        pre[a[1]]=1;
        for(int i=2;i<=n;i++){
            ed=max(pre[a[i]],ed);
            if(ed == 0)
                dp[i]=sum[i-1] ,dp[i]++;
            else
                dp[i]=((sum[i-1]-sum[ed-1])+MOD)%MOD;
            sum[i]=( dp[i] + sum[i-1])%MOD;
            pre[a[i]] = i;
        }
//        for(int i=1;i<=n;i++)
//            printf("dp[%d] %d\n",i,dp[i]);
        printf("%d\n",dp[n]);
    }
    return 0;
}


2017-03-18 21:28
2
//第一题

#include <stdlib.h>

#include <stdio.h>

#include <string.h>

#include <string>

#include <algorithm>

#include<math.h>

using namespace std;


int main()

{

    double l,r;

double pi=3.141592654;

while(scanf("%lf%lf",&l,&r)==2)

{    


    double c=2*pi*r;

double sita=(l/c)*2*pi;

double sita2=(-l/c)*2*pi;

//printf("c=%lf l=%lf l/c=%lf\n",c,l,sin(30/180.0*pi));

         // printf("%lf\n",sin(sita));

double y=sin(sita)*r;

double x=cos(sita)*r;

double y1=sin(sita2)*r;

double x1=cos(sita2)*r;


printf("%.3lf %.3lf\n",x1,y1);

printf("%.3lf %.3lf\n",x,y);

}

return 0;

}

//第二题

#include <stdlib.h>

#include <stdio.h>

#include <string.h>

#include <string>

#include <algorithm>

#include<math.h>

using namespace std;

int a[100000+5];

int n;

int geti(int l,int r)

{

if(l==r)

return 1;

    int i,j,k=-1;

for(i=l;i<=r;i++)

{

for(j=i+1;j<=r;j++)

{

if(a[i]==a[j])

return (geti(l,j-1)*geti(j,r))%1000000007;

}

}

int ans=pow(2.0,(r-l));

return ans%1000000007 ;

}



int main()

{

     while(scanf("%d",&n)==1)

{

int i;

for(i=0;i<n;i++)

scanf("%d",&a[i]);

int ans=pow(2.0,n-1);

        printf("%d\n",geti(0,n-1));

}

    

return 0;

}



2017-03-18 21:31

第二题第三题,n^2真的可以吗

2017-03-18 21:32
fwm94 回复 acmcoderBuX1Jjh4

第二题只要所有子串中不出现相同数字,没要求所有子串不同,请仔细读题

2017-03-18 21:32
fwm94 回复 蜗牛侠

第二题不是n^2,第三题是n^2

2017-03-18 21:33
小码快跑 回复 蜗牛侠

同学可以在上面的真题练习链接去测试下~

2017-03-18 21:33

通过80%+,求解

import java.util.Scanner;

public class Main{
	public static void main(String[] args) {
		Scanner scanner = new Scanner(System.in);

		int cnt = scanner.nextInt();

		int[][] result = new int[cnt][2];

		for (int i = 0; i < cnt; i++) {
			int N = scanner.nextInt();
			int[] money = new int[N];
			for (int j = 0; j < N; j++) {
				money[j] = scanner.nextInt();
			}
			int m = 0, n = N - 1;
			for (int j = 0; j < N; j++) {
				if (j % 2 == 0) {
					if (money[m] >= money[n]) {
						result[i][0] += money[m];
						m++;
					} else {
						result[i][0] += money[n];
						n--;
					}
				} else {
					if (money[m] >= money[n]) {
						result[i][1] += money[m];
						m++;
					} else {
						result[i][1] += money[n];
						n--;
					}
				}
			}
		}
		for (int i = 0; i < result.length; i++) {
			System.out.printf("Case #%d: %d %d\n", (i + 1), result[i][0], result[i][1]);
		}
	}
}


2017-03-18 21:33
fwm94 回复 acmcoderyByjrJBy

你这是贪心算法,请仔细阅读题解

2017-03-18 21:37
多喝热水 回复 fwm94

详细题解在群里有链接

2017-03-18 21:39
acmcoderBuX1Jjh4 回复 fwm94

看了好几遍,我只能说,这题题目不明,有明显的歧义

2017-03-18 21:40
coder_JEJPYETG 回复 acmcoder2ctwnChP

两伙马贼均会采取对己方有利的策略,dp只是对A有利呀

2017-03-18 21:43

忘记算法了...

2017-03-18 21:44
acmcodernOE00yWs 回复 coder_JEJPYETG

先选的必选全局最大值,后选的只能选可以选到的最大值

2017-03-18 21:49

跑步:

import java.text.DecimalFormat;

import java.util.Scanner;


public class Main {


public static void main(String args[]){

       

    Scanner scanner=new Scanner(System.in);

     

    Double r=0.0;

    Double L=0.0;

    Double pi=Math.PI;

   

     

     

     

    L=scanner.nextDouble();

    r=scanner.nextDouble();

     

    Double temp=(360*L)/(2*pi*r);

     

    

     

    //顺时针坐标

    Double x1=0.0;

    Double y1=0.0;

    //逆时针坐标

    Double x2=0.0;

    Double y2=0.0;

     

    

   

    x1=r*Math.cos(Math.toRadians(-temp));

    y1=r*Math.sin(Math.toRadians(-temp));

     

     

    x2=r*Math.cos(Math.toRadians(temp));

    y2=r*Math.sin(Math.toRadians(temp));

    

     

   

    DecimalFormat df=new DecimalFormat("0.000");

    System.out.println(df.format(x1)+" "+df.format(y1));

    System.out.println(df.format(x2)+" "+df.format(y2));

   

     }

}



2017-03-18 21:52
1
fwm94 回复 coder_YGD45UF9

第二层循环有break,最多跑10次就退出!

2017-03-18 21:59
第三题只通过了29%,为什么啊
import java.util.ArrayList;
import java.util.Scanner;

public class Main {

   public static void main(String[] args) {

       Scanner sc=new Scanner(System.in);
      ArrayList<String> list=new ArrayList<>();
           int times=sc.nextInt();
           for(int i=0;i<times;i++){
               int parts=sc.nextInt();
               int[] arr=new int[parts];
               for(int j=0;j<parts;j++){
                   int temp=sc.nextInt();
                   arr[j]=temp;
               }
           int resultA=0;
               int resultB=0;
               int head=0;
               int tail=arr.length-1;
               boolean turnA=true;
for(int k=0;k<arr.length;k++){
   if(turnA==true){
       if(arr[head]>=arr[tail]){
           resultA+=arr[head];
           head++;
           turnA=false;
       }else{
           resultA+=arr[tail];
           tail--;
           turnA=false;
       }
   }else{
       if(arr[head]>=arr[tail]){
           resultB+=arr[head];
           head++;
           turnA=true;
       }else{
           resultB+=arr[tail];
           tail--;
           turnA=true;
       }
   }
}
if(resultA>resultB) {
   list.add("Case #"+(i+1)+": "+resultA + " " + resultB);

}else{
   list.add("Case #"+(i+1)+": "+resultB + " " + resultA);
}

           }
          for(int i=0;i<list.size();i++){
              System.out.println(list.get(i));
          }


       }



2017-03-18 22:09
1
acmcoderuKX3BrmG 回复 多喝热水

群号呢?

2017-03-18 22:33

还是有很大的差距的!

2017-03-19 00:35

#include <stdlib.h>

#include <stdio.h>

#include <string.h>

#include <string>

#include <algorithm>

#include<math.h>

using namespace std;

int a[100000+5];

int n;

int f[11];

int dp[100000+5];

int geti()

{

memset(f,0,sizeof(f));

    memset(dp,0,sizeof(dp));

int i,j;

dp[0]=1;

for(i=1;i<n;i++)

{

memset(f,0,sizeof(f));

f[a[i]]=1;

for(j=i-1;j>=0;j--)

{   

dp[i]=(dp[i]+dp[j])%1000000007;

//从后往前切,每切一刀的结果就是切的前一段的所有的可能

if(f[a[j]])

break;

             f[a[j]]=1;

}

if(j==-1)

dp[i]++;

//处理特殊情况:1.遇到已经切过得颜色,就结束了不能往前切了,假如 没有同颜色的需要多加一种可能那就是一刀不切

}

return dp[n-1]%1000000007;

}

int main()

{

     while(scanf("%d",&n)==1)

{

int i;

for(i=0;i<n;i++)

scanf("%d",&a[i]);

int ans=pow(2.0,n-1);

        printf("%d\n",geti());

}

    

return 0;

}



2017-03-19 02:21
2

加油!

2017-03-19 09:25

第一、二题都是百分之七十,第三题都差点没看到,没做完,这还有机会吗

2017-03-19 09:49

请问你们收到面试通知了吗


2017-03-20 10:48
小码快跑 回复 acmcoderjPH6nooY

360校招网站面试安排是3月27日开始,估计会等到25日那批结束后统一发放吧,同学请以360官方信息为准

2017-03-20 11:17

第三题贪心法只过了28%

2017-03-20 19:25
小码快跑 回复 acmcoderseeYE1kz

不错哦,第三题还是有一定难度的,像小码这样还在努力学习提高的萌新,还看不懂题意_(:°з」∠)_

2017-03-21 09:58

唉...

2017-03-23 17:41

还是视频题解有意思啊!

2017-03-25 21:18
4

仅以此表情表达我心情

2017-03-25 21:24
coder_CTCNPFUZ 回复 赛码张三

嗯……文字的有些难理解

2017-04-01 11:16
添加回复
回到顶部