indeed秋招笔试第一场

做了indeed秋招的第一场笔试,题目相比别家确实简单。其中前三道完全是水题,记录一下~

第一题:Tabereru

题意:给定一个字符串,遇到"ra"需要删除,但是删除之后如果又出现了"ra"那么不继续删除了。即如果输入是rrraaa,那么输出是rraa。

思路:字符串很短,随便搞就OK。


第二题:Matrix Product

题意:就是裸的矩阵乘法,复杂度不需要任何优化,O(n^3)即可。


第三题:Ancient Formula

题意:给定不超过6个数,其中有5个空位可以添加加号+或者乘号*,求值的时候不考虑优先级,即2+3*4=20。再给定一个整数k,问这6个数的某种排列以及某种加符号方式下,与k的差的绝对值的最小值(即与k的接近程度)。

#include <cstdio>
#include <cstring>
#include <string>
#include <cstdlib>
#include <vector>
#include <queue>
#include <algorithm>
#include <cmath>
#include <map>
#include <set>
#include <iostream>
#define N 505
#define INF 0x7fffffff
using namespace std;
int n,k,res = INF;
vector<int> s;
void solve(vector<int> &s,int d,int now){
    if(d == s.size()){
        res = min(res,abs(now-k));
        return;
    }
    solve(s, d+1, now+s[d]);
    solve(s, d+1, now*s[d]);
}
void dfs(vector<int> &s,int d,vector<bool> &used,vector<int> &tmp){
    if(d == s.size()){
        solve(tmp, 1, tmp[0]);
        return;
    }
    for(int i = 0;i<s.size();i++){
        if(!used[i]){
            tmp[d] = s[i];
            used[i] = true;
            dfs(s, d+1, used, tmp);
            used[i] = false;
        }
    }
    
}
int main(){
    scanf("%d %d",&n,&k);
    for(int i = 0;i<n;i++){
        int x;
        scanf("%d",&x);
        s.push_back(x);
    }
    if(n == 1){
        printf("%d\n",abs(s[0]-k));
        return 0;
    }
    vector<bool> used(s.size(),false);
    vector<int> ans(s.size());
    dfs(s,0,used,ans);
    printf("%d\n",res);
    return 0;
}


第四题:Painting

题意:输入n(n<=100000),表示n个白球在一条线上。每次等概率在不与黑球相邻的白球中选择一个置为黑球,直到没有这样的白球。问最后剩下的黑球的期望。输出float,精度10e-8之内。

样例:n=1和2下显然期望为1。n=3的时候,第一次有2/3的概率选择两边的白球,此时必然会选择第二个白球(另一边的边上);第一次还有1/3的概率选择中间的球,此时只会选择这一个球,最终的期望是5/3。

思路:dp咯。一个显然的dp如下:dp[x]表示初始有x个白球的期望。分类第一个白球选择的位置(1~n):如果选在了最边上的1号球,那么剩下变成了在3~n中继续选球;如果选择了2号,那么接下来在4~n中选择;如果选择了3号,那么接下来在1号以及5~n号中选择;同理,如果选择的是i号球,那么接下来从1~i-2和i+2~n中分别选择。但是这个dp的复杂度是O(n^2)级别的,太高了。

如何降到O(n)?考虑上述dp的结果(为方便令dp[0]=0),通过一个具体的例子解释吧:n=6的时候dp(x)=1/3(1 + dp(4)) + 1/3(1 + dp(0) + dp(3)) + 1/3(1 + dp(1) + dp(2)) = 1/3 * (3+dp(0)+...+dp(4))。推广到一般的偶数x,dp(x) = (2/x)*(x/2 + dp(0) + ... + dp(x-2))。同理可以推得n为奇数时候的公式,可知与前n项和有关,记录一下即可。这样的dp复杂度就降低为O(n)啦。

#include <cstdio>
#include <cstring>
#include <string>
#include <cstdlib>
#include <vector>
#include <queue>
#include <algorithm>
#include <cmath>
#include <map>
#include <set>
#include <iostream>
#define N 100005
#define INF 0x7fffffff
using namespace std;
int n;
double dp[N];
int main(){
    scanf("%d",&n);
    for(int i = 2;i<=n;i++)
        dp[i] = -1;
    dp[0] = 0;
    dp[1] = dp[2] = 1;
    double sum = 1;
    for(int i = 3;i<=n;i++){
        if(i&1)
            dp[i] = (sum-dp[(i-3)>>1]+i/2)*2/i + (1+2*dp[(i-3)>>1])/i;
        else
            dp[i] = (sum+(i>>1))/(i>>1);
        sum += dp[i-1];
    }
    printf("%.10lf\n",dp[n]);
    return 0;
}


实际上对于奇数情况,如果把式子乘出来再次化简,可以得到和偶数相同的形式,而且求dp[i]的时候只与前i-2项的和有关,从而连dp这个数组也可以省略:代码如下:

#include <cstdio>
#include <cstring>
#include <string>
#include <cstdlib>
#include <vector>
#include <queue>
#include <algorithm>
#include <cmath>
#include <map>
#include <set>
#include <iostream>
#define N 100005
#define INF 0x7fffffff
using namespace std;
int n;
int main(){
    scanf("%d",&n);
    
    double res = 1, sum = 1;
    for(int i = 3;i<=n;i++){
        double tmp = res;
        res = 2.*sum/i + 1;
        sum += tmp;
    }
    printf("%.10lf\n",res);
    return 0;
}



评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值