微软2016校招笔试 第二场部分题目个人思路

A. Lucky Substrings

这道题并不难,由于字符串长度只有100,那么它的子串肯定不超过1w个,枚举出所有字串都是没有问题的,至于检验一个子串里面不同的字母数量是不是斐波那契数,我们只需要事先把斐波那契数列小于1w的项都生成出来,然后枚举一个子串之后,统计出不同字母的数量(边找边统计,如果当前字母之前出现过就不加,如果没出现过就记住并+1),去这个里面找就行了。斐波那契数列推不了几项就到1w了……

最后要字典序从小到大排列,并且还要去重,那就用string然后直接sort+unique一发,搞定

#include<iostream>
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<string>
#include<algorithm>
using namespace std;

char s[200];
string ans[20000];
int p_ans=0;

int fib[10000];
int p_fib=0;

void gener_fb()
{
    fib[1]=1;
    fib[2]=1;
    int i=3;
    while(true)
    {
        fib[i] = fib[i-1]+fib[i-2];
        if(fib[i]>100)
        {
            p_fib =i;
            return;
        }
        i++;
    }
}

bool find(int x)
{
    for(int i=1; i<=p_fib;i++)
    {
        if(fib[i] == x)
            return true;
    }
    return false;
}

int main()
{
    gener_fb();

    cin>>s;
    int len=strlen(s);
    int i;
    for(i=0;i<len;i++)
    {
        char now[200]={0};
        int appear[200]={0};
        int sum_appear=0;
        for(int j=i; j<len; j++)
        {
            now[j-i] = s[j];

            if(appear[s[j]]==0)
            {
                appear[s[j]]=1;
                sum_appear ++;
            }
            if(find(sum_appear))
            {
                string str(now);
                ans[++p_ans] = str;
            }
        }
    }
    sort(&ans[1], &ans[p_ans+1]);
    p_ans = unique(&ans[1], &ans[p_ans+1]) - ans-1;
    for(i=1;i<=p_ans;i++)
    {
        cout<<ans[i]<<endl;
    }
    //system("pause");
    return 0;
}

B. Numeric Keypad

这道题我还是想了一会的,我也不知道其他人是怎么做的……

这道题可以注意到这么几点,首先就是输入的数特别大,有500位,所以我们肯定是要一位一位处理,每一位都要尽量和输入的一样,因为如果前面有一位小了,后面再大也没用;

关键问题是有的时候如果你输的一样的话,后面就不行了,比如样例的131,你如果第二位输了3,那你会发现第三位无解了。怎么办呢?其实很容易,这个时候我们只需要回退到上一层并尝试一个更小的数字即可。你会发现这样的回退最多只会出现一次,因为一旦回退之后,后面的你都可以无脑的填了。如果回退的那一位不是0的话,那么你后面可以无脑填9,比如131你回退到12的时候,后面你都不用想了,肯定全填9,反正你在第二位已经比他小了;如果回退这一位是0的话就不行了,因为0到不了9,就只能后面全无脑填0了,比如876这个例子答案就是800.

建议预先处理一个map[i][j],表示数字i能不能到数字j去,这样会给你后面省很多事。

#include<iostream>
#include<string.h>
#include<math.h>
#include<stdio.h>
#include<algorithm>
using namespace std;

char input[600];
int t;

int map[10][10];

int ans[600];

void initmap()
{
    int i,j;
    for(i=1;i<=9;i++)
    {
        for(j=1;j<=9;j++)
        {
            if( (i-1)/3 <= (j-1)/3 && (i-1)%3 <=(j-1)%3)
                map[i][j]=1;
        }
    }
    for(i=1;i<=7;i+=3)
        map[i][0]=1;
    for(i=2;i<=8;i+=3)
        map[i][0]=1;
    map[0][0]=1;
    return;
}

bool go(int pos, int last)
{
    if(pos==strlen(input))
        return true;

    int now = input[pos]-‘0‘;
    bool ok=false;
    for(int i=now; i>=0; i--)
    {
        if(map[last][i]==1)
        {
            ans[pos]=i;
            if(i==now)
            {
                if(go(pos+1, i) == false)
                {
                    continue;
                }
                else
                    return true;
            }
            else
            {
                for(int tmp=pos+1; tmp<strlen(input); tmp++)
                {
                    if(i==0)
                        ans[tmp]=0;
                    else
                        ans[tmp]=9;
                }
                return true;
            }
        }
    }
    return false;
}

void init()
{
    memset(ans,0,sizeof(ans));
}

int main()
{
    initmap();

    cin>>t;
    for(int files=1; files<=t; files++)
    {
        init();
        cin>>input;

        go(0,1);

        for(int i=0; i<strlen(input);i++)
            cout<<ans[i];
        cout<<endl;
    }
    //system("pause");
    return 0;
}

C. Spring Outing

这题当时我的算法WA了,然后想了半天也没想出来哪儿错,后来今天讨论才知道的……

这道题目的关键就在于“已经知道的肯定可以去的地方”,一开始大家都知道“我至少可以待在家里”。

那么考虑这么一个事情,对于某一个人来说,如果前面所有的地点都被pass掉了,现在投K的话,如果K在0后面,那我肯定不投;如果K在0前面,那我肯定就要投,不然没别的选择我就得在家呆着了;这样,我们根据所有人的行为就能知道K到底能不能去,如果有一半人都会投K的话,那么K就可以去了,反之K就不能去;

同样的道理,如果K可以去了,我们看K-1的时候,如果某个人更想去K-1,那他一定会投的,否则一定不会投的。当然如果刚才结果是K去不了,那么现在最后一个肯定能去的选择就是0,就变成了K-1和0之间的选择。

所以,我们只需要从第K号地点往前试,试完K个就知道他们会在哪个地点达到第一次(也就是我们这个算法当中的最后一次)过半数了。

由于输入都是0~n的排列,所以我们可以将每个数在每个人当中的位置记录下来,这样找起来就非常方便了。

注意,并不是说一个人绝对不会投一个已知可取的地方的后面的票的,比如一个人的志愿是0 1 2,那么根据刚才的结论,如果2已经可以去了,他还是会投1的,要不然就铁定去2了。并不是说一个人想在家呆着就一定会一直憋着。

本题由于还没有开放,所以就不贴代码了。

时间: 2024-12-22 02:14:26

微软2016校招笔试 第二场部分题目个人思路的相关文章

微软2016校招笔试 第一场部分题目个人思路

嗯--第一场当时还不知道报名,第二场报上了,拿了250/400,果然分如其人-- 这里包括的是第一场的ABC题,第二场的AB题的题解在另一篇(这些都是自己AC了的),第一场的D和第二场的C至今仍然在WA,不知道怎么回事,到时候也讲讲思路求指点吧. A. Magic Box 这道题并不难做,唯一需要注意的是cx,cy和cz,以及任意两个量的差之间是没有前后关系的(这个事情样例里也告诉你了),所以比较简单的方法就是先把cx,cy,cz排序,然后根据输入串一个一个模拟,然后计算出两两之间的差,排序,比

2017年校招全国统一模拟笔试(第二场)编程题集合-牛客网

 2017年校招全国统一模拟笔试(第二场)编程题集合-牛客网 链接:https://www.nowcoder.com/questionTerminal/276712b113c6456c8cf31c5073a4f9d7来源:牛客网 牛牛有两个字符串(可能包含空格),牛牛想找出其中最长的公共连续子串,希望你能帮助他,并输出其长度. 输入描述: 输入为两行字符串(可能包含空格),长度均小于等于50. 输出描述: 输出为一个整数,表示最长公共连续子串的长度. 输入例子: abcde abgde 输出例子

微软2017年预科生计划在线编程笔试第二场 Queen Attack

排序. 分别按照$x$,$y$以及对角线排序,统计一下方案数就可以了. #include<bits/stdc++.h> using namespace std; int n; struct X { int x,y; }s[100010]; bool cmp1(X a, X b) { return a.x<b.x; } bool cmp2(X a, X b) { return a.y<b.y; } bool cmp3(X a, X b) { return a.x+a.y<b.x

微软2017年预科生计划在线编程笔试第二场 Diligent Robots

模拟. 不断分裂,然后计算时间,取个最小值.我也不知道这做法对不对的,读完题猜了一下,抱着$WA$的心态$submit$了,然后跳出一个$AC$. #include<bits/stdc++.h> using namespace std; long long n; int q; int main() { scanf("%lld%d",&n,&q); long long now=1; long long ans=n; long long ci=0; while(

微软2017年预科生计划在线编程笔试第二场 EL SUENO

树上背包. 简单的树形$dp$,计算出摧毁每一个节点所需的最小费用,背包即可. #include<bits/stdc++.h> using namespace std; struct X { int fa; int in; int ip; int c; }s[2010]; int dp[2010][20010]; int cost[2010]; int f[20010]; vector<int>g[2010]; int n,root,ans; void dfs(int x) { i

一道校招笔试的C语言题目

今天想起一道原先参加校招的一道题目,其原理是C语言挺基础的东西,但很多人都答错了.     struct test {                 int a;         int *c;     };          struct test b;     b.a = 300;     b.c = 500;     printf("%d", b.a + b.c); 大家先想一下结果是多少,然后再运行一下验证验证.想一下是什么原理

微软苏州校招笔试 12月27日

题目1 : Lost in the City 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 Little Hi gets lost in the city. He does not know where he is. He does not know which direction is north. Fortunately, Little Hi has a map of the city. The map can be considered as a grid

【hihocoder】1237 : Farthest Point 微软2016校招在线笔试题

题目:给定一个圆,要你求出一个在里面或者在边上的整数点,使得这个点到原点的距离最大,如果有多个相同,输出x最大,再输出y最大. 思路:对于一个圆,里面整点个数的x是能确定的.你找到x的上下界就可以了.就是mix = ceil(x0-r)//因为是小的值,所以要向上取整.mxx=floor(x0+r)//大的值要向下取整 对于y.我们也能用欧股定理确定.y也是有一个范围.但是并不是所有y都要枚举的.明显.y的值是离圆心越远越好.所以对于每一个x而言只需要枚举最远的两个y值 #include <cs

[HiHoCoder]#1094 : Lost in the City 微软苏州校招笔试 12月27日

时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 Little Hi gets lost in the city. He does not know where he is. He does not know which direction is north. Fortunately, Little Hi has a map of the city. The map can be considered as a grid of N*M blocks. Each blo