2017Nowcoder Girl初赛重现赛

题目总体不算难。
但是DP太弱。状压写不来。
我还是有点菜。
总体体验的话,就是数据量小,你尽管暴力。


A
打表以后 ,upper_bound 查找一下即可

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll a[100005];
int main()
{
    for(int i=1;i<=100000;i++)
    {
        a[i]=(ll)i*i;
    }
    ll n;
    cin>>n;
    int t = upper_bound(a+1,a+100000,n)-a;
    //cout<<t<<endl;
    cout<<a[t-1]<<endl;
    return 0;
}

B
N可以得到 奇数,G可以得到偶数,给定n ,倒推回去就可以

#include <bits/stdc++.h>
using namespace std;
char ch[]= {'N','G'};
vector<int>v;
int main()
{
    int n;
    cin>>n;
    while(n)
    {
        if(n%2==0)
        {
            v.push_back(1);
            n=(n-2)/2;
        }
        else
        {
            v.push_back(0);
            n=(n-1)/2;
        }
    }
    int len = v.size();
    for(int i=len-1;i>=0;i--)
    {
        printf("%c",ch[v[i]]);
    }
    printf("\n");
    return 0;
}

C 从左往后搜索,模拟交换即可

#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5+50;
const int mod=1e9+7;
int a[maxn];
int n;
typedef long long ll;
ll change(int x)
{
    for(int i=x+1;i<=n;i++)
    {
        swap(a[i],a[i-1]);
        if(a[i]!=i) return i-x;
    }
    return 0;
}
int main()
{
    //int n;
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
    }
    ll ans=0;
    for(int i=1;i<=n;i++)
    {
        if(a[i]==i) ans +=change(i);
    }
    cout<<ans<<endl;
    return 0;
 
}

D
n 只有10 ,暴力每一种选法,判断删去最小数能否成立,选择其中数目最多的即可

#include <bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define sc(x) scanf("%d",&x)
using namespace std;
int n,s;
int p[20];
int a[20];
int main()
{
    cin>>n>>s;
    for(int i=0;i<n;i++)
    {
        cin>>p[i];
    }
    int ans=0;
    for(int i=1;i<(1<<n);i++)
    {
        bitset<11>ch(i);
        int mmin=100000;
        int cnt=0;
        int tmp=0;
        for(int j=0;j<n;j++)
        {
            if(ch[j]==1)
            {
                mmin = min(mmin,p[j]);
                tmp +=p[j];
                cnt++;
            }
        }
        if(tmp-mmin<s&&tmp>=s) ans = max(ans,cnt);
    }
    cout<<ans<<endl;
    return 0;
}

E题
状压dp
对于 k>=5的情况,显然选择每个状态的最大值即可
但是对于k<5的情况
首先,我们可以将k小于5的情况 分解
假设 k=4
那么我们可以取1个含有5种属性的最大值,或者两个拼成5种属性的最大值,或者3个、4个
那么,我们枚举每一种拼法。在这种拼法下,取求得含有指定种属性值的最大的装备
然后将其拼凑在一起即可
dp[i][j] 表示 状态i 下,j个子集组合起来的最大值
对于每一种状态 u,v
i= u|v
d p [ i ] [ j ] = m a x ( d p [ i ] [ j ] , d p [ u ] [ j 1 ] + d p [ v ] [ 1 ] ) dp[i][j] = max(dp[i][j],dp[u][j-1]+dp[v][1]) dp[i][j]=max(dp[i][j],dp[u][j1]+dp[v][1])

#include <bits/stdc++.h>
#define cl(a) memset(a,0,sizeof(a))
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=1e5+50;
typedef long long ll;
ll a[maxn][6];
ll r[6];
ll dp[1<<5][6];
ll ans=0;
int main()
{
    int n,k;
    cin>>n>>k;
    rep(i,1,n) rep(j,1,5)
    {
        cin>>a[i][j];
        r[j]=max(r[j],a[i][j]);
    }
    if(k>=5)
    {
        ans = r[1]+r[2]+r[3]+r[4]+r[5];
        cout<<ans<<endl;;
        return 0;
    }
    else
    {
        dp[0][0]=0;
        ans=0;
        for(int i=0; i<(1<<5); i++)
        {
            bitset<5>ch(i);
            rep(j,1,n)
            {
                ll tmp = 0;
                rep(k,0,4)
                {
                    if(ch[k]!=0) tmp+=a[j][k+1];
 
                }
                dp[i][1]=max(dp[i][1],tmp);
            }
            ans = max((ll)dp[i][1],ans);
        }
        rep(v,2,k)
        {
            rep(i,0,31) rep(j,0,31)
            {
                if(!(i&j))
                {
                    dp[i|j][v] = max(dp[i|j][v],dp[i][v-1]+dp[j][1]);
                    ans = max(dp[i|j][v],ans);
                }
            }
        }
        cout<<ans<<endl;
    }
 
    return 0;
}

F
简单dp
类似背包
d p [ i ] [ j ] dp[i][j] dp[i][j]表示前i种物品 共j颗珠子的方案数
d p [ i ] [ j ] + = d p [ i 1 ] [ j k ] ( l i k r i ) dp[i][j] += dp[i-1][j-k] (l_{i} \le k \le r_{i}) dp[i][j]+=dp[i1][jk](likri)

#include <bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=1e5+50;
typedef long long ll;
ll dp[30][150];
ll r[30],l[30];
int main()
{
    int n,m;
    cin>>n>>m;
    rep(i,1,n) cin>>l[i]>>r[i];
    dp[0][0]=1;
    rep(i,1,n) rep(j,0,m)
    {
        rep(k,l[i],r[i])
        if(j-k>=0)
        dp[i][j]+=dp[i-1][j-k];
        //cout<<i<<" "<<j<<" "<<dp[i][j]<<endl;
    }
    cout<<dp[n][m]<<endl;
    return 0;
 
}
全部评论

相关推荐

点赞 评论 收藏
分享
不愿透露姓名的神秘牛友
10-05 10:13
已编辑
HHHHaos:让这些老登来现在秋招一下,简历都过不去
点赞 评论 收藏
分享
评论
点赞
收藏
分享
牛客网
牛客企业服务