个人赛改题

题目链接:https://cn.vjudge.net/contest/243243#overview

A题:

一道完全背包题,由于都是1000的整数倍注意除1000省空间

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
int dp[100005];
int value[11],interest[11];
int main()
{
    ios::sync_with_stdio(0),cin.tie(0);
    int t;
    cin>>t;
    int start,year;
    while(t--)
    {
        cin>>start>>year;
        int d;
        cin>>d;
        for(int i=1;i<=d;i++)
            cin>>value[i]>>interest[i];
        while(year--){
        int s=start/1000;
        memset(dp,0,sizeof dp);
        for(int i=1;i<=d;i++){
            for(int j=value[i]/1000;j<=s;j++)///区分和0-1背包的区别,0-1背包是逆向循环,完全背包是正向
              dp[j]=max(dp[j],dp[j-value[i]/1000]+interest[i]);
        }
        start+=dp[s];///利息加本金
        }
    cout<<start<<endl;
    }
    return 0;
}

F题:

由于物品都是3的整数倍,可以想到化为3进制来做

把n化为3进制有三种情况

1、位数上为0不处理

2、位数上为1放在右边

3、位数上为2,由于每个物品只有一个,应在左边相应的位上加1使其满3进位

最后统计每边有几个1就应放几个物品。

举个栗子:左边是42,化为3进制为1120,加上1110后就变为了10000(右边),所以左边加3个物品(3,9,27),右边加一个(81)

AC code:

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
typedef long long ll;
ll f[20];
ll l,r;
ll Pow(ll n)
{
    ll ans=1;
    while(n--)
        ans*=10;
    return ans;
}
void div(ll n)
{
    int pos=0;
    while(n)
    {
        int t=n%3;
        n/=3;
        if(t==1)
            r+=Pow(pos);
        else if(t==2)
        {
            l+=Pow(pos);
            n++;
        }
        pos++;
    }
}
int getsum(ll n)
{
    int res=0;
    while(n)
    {
        if(n%10)
          res++;
        n/=10;
    }
    return res;
}
void print(ll n)
{
    int pos=0;
    while(n)
    {
        if(n%10)
         printf(" %d",f[pos]);
       n/=10;
       pos++;
    }
    printf("\n");
}
int main()
{
    f[0]=1;
    for(int i=1;i<20;i++)
        f[i]=3*f[i-1];
        ll n;
        while(~scanf("%lld",&n)){
        l=r=0;
        div(n);
        printf("%d",getsum(l));
        print(l);
        printf("%d",getsum(r));
        print(r);
        }
    return 0;
}

H题:

没什木说的,贴两个素数打表吧

1、

void set_prime()
{
    cnt=0;
    for(int i=2;i<=N;i++)
    if(!vis[i]){
        prime[cnt++]=i;
        for(int j=1;i*j<=N;j++)
            vis[i*j]=1;
    }
}

2、

void set_prime()
{
    cnt=0;
    memset(vis,0,sizeof vis);
    for(int i=2;i<=N;i++)
    if(!vis[i]){
        prime[cnt++]=i;
        for(int j=i+i;j<=N;j+=i)///与第一种不同
            vis[j]=1;
    }
}

AC code:

#include<iostream>
#include<cstring>
#include<cmath>
#include<cstdio>
using namespace std;
int prime[1000001];
int vis[1000001]={0};
int cnt,m[1000001];
void set_prime()
{
    cnt=0;
    //memset(vis,0,sizeof vis);
    for(int i=2;i<1000000;i++)
    if(!vis[i]){
        prime[cnt++]=i;
        m[i]=cnt;
        for(int j=i+i;j<1000000;j+=i)
            vis[j]=1,m[j]=cnt;
    }
}
int main()
{
    set_prime();
    int n;
    while(scanf("%d",&n)!=EOF&&n){
    printf("%d\n",m[n]);
    }
    return 0;
}

J题:

一道基础dp题,就是把二维分开求,先求每行的不连续序列最大值,把每行的最大值有当成一个数组,求该数组的不连续最大值

AC code:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=2e5+1;
int a[maxn],b[maxn],choose[maxn],no[maxn];///choose表示第i个选,no表示第i个不选
int Dp(int *a,int len)
{
    choose[1]=a[1],no[1]=0;
    for(int i=2;i<=len;i++){
        choose[i]=no[i-1]+a[i];///第i个选了=第i-1个不选+a[i]
        no[i]=max(choose[i-1],no[i-1]);///第i个不选等于第i-1选或不选的最大值
    }
    return max(choose[len],no[len]);
}
int main()
{
    ios::sync_with_stdio(0),cin.tie(0);
    int n,m;
    while(cin>>n>>m){
    //memset(choose,0,sizeof choose);
    //memset(no,0,sizeof no);
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
            cin>>a[j];
        b[i]=Dp(a,m);///记录每行的最大值
    }
    cout<<Dp(b,n)<<endl;///找出每行最大值中最大的
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/shaohang_/article/details/81434354