11.29杭电校赛

1001、搬砖

description.刚开始一堆砖,共N块;任务是要把它分成N堆,每堆1块。

分的过程中,每次可将一堆分成两堆,耗费的体力是分完之后的两堆砖的数目的差值。

求完成任务需要耗费的最小的体力。

solution.贪心:每次分完之后的这两堆的数目差值越小,耗费的体力越小。

即每次分成差值最小的两堆,保证最后的耗费最小。

证明:(1)贪心选择性质:学的渣。。。不大会啊。

(2)最优子结构性质:~~~

code.现求

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

int dfs(int n){
    if(n==1)return 0;
    if(n&1)return dfs(n/2)+dfs(n/2+1)+1;//奇数
    return dfs(n/2)*2;//偶数
}

int main(){
    int T;
    int N;
    scanf("%d",&T);
    while(T--){
        scanf("%d",&N);
        printf("%d
",dfs(N));
    }
    return 0;
}
View Code

code2.打表

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

const int MAXN=10000010;
int ans[MAXN];

void f(){
    ans[0]=0;
    ans[1]=0;
    for(int i=2;i<MAXN;++i){
        if(i&1){
            ans[i]=ans[i/2]+ans[i/2+1]+1;
        }
        else{
            ans[i]=ans[i/2]+ans[i/2];
        }
    }
}

int main(){
    f();
    int T;
    int N;
    scanf("%d",&T);
    while(T--){
        scanf("%d",&N);
        printf("%d
",ans[N]);
    }
    return 0;
}
View Code

1002、投币洗衣机

d.题意比较简单,给出过去n天每天换下的衣服数目。在每一天,如果 a<=衣服数目<b ,花费2去洗;如果 b<=衣服数目<c ,花费3去洗;如果 c<=衣服数目 ,花费4去洗。

求这n天洗衣服花的钱。

s.模拟:从第一天开始,模拟到最后就可以了。

c.

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

int main(){
    int n,a,b,c;
    int sum,t;
    int ans;
    while(~scanf("%d%d%d%d",&n,&a,&b,&c)){
        sum=0;
        ans=0;
        while(n--){
            scanf("%d",&t);
            sum+=t;
            if(a<=sum&&sum<b){
                sum=0;
                ans+=2;
            }
            else if(b<=sum&&sum<c){
                sum=0;
                ans+=3;
            }
            else if(c<=sum){
                sum=0;
                ans+=4;
            }
        }
        printf("%d
",ans);
    }
    return 0;
}
View Code

1003、玩骰子

d.

s.枚举即可

c.

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

int ntype,atype;//1散牌,2对子,3三条

bool win(int n[],int a[]){
    if(ntype>atype)return true;
    if(ntype==atype){
        if(ntype==1){
            if(n[2]>a[2])return true;
            if(n[2]==a[2]){
                if(n[1]>a[1])return true;
                if(n[1]==a[1]){
                    if(n[0]>a[0])return true;
                }
            }
            return false;
        }
        if(ntype==2){
            if(n[1]>a[1])return true;
            if(n[1]==a[1]){
                int ntemp,atemp;

                if(n[0]==n[1])ntemp=n[2];
                else ntemp=n[0];

                if(a[0]==a[1])atemp=a[2];
                else atemp=a[0];

                if(ntemp>atemp)return true;
            }
            return false;
        }
        if(ntype==3){
            if(n[0]>a[0])return true;
            return false;
        }
    }
    return false;
}

int main(){
    int T;
    int n[3],a[3];
    int n2[3];

    scanf("%d",&T);
    while(T--){
        scanf("%d%d%d",&n[0],&n[1],&n[2]);
        scanf("%d%d%d",&a[0],&a[1],&a[2]);
        sort(n,n+3);
        sort(a,a+3);

        if(n[0]!=n[1]&&n[0]!=n[2]&&n[1]!=n[2])ntype=1;
        else if(n[0]==n[1]&&n[1]==n[2])ntype=3;
        else ntype=2;

        if(a[0]!=a[1]&&a[0]!=a[2]&&a[1]!=a[2])atype=1;
        else if(a[0]==a[1]&&a[1]==a[2])atype=3;
        else atype=2;

        if(win(n,a)){
            printf("1.000
");
            continue;
        }

        double ans=0;//胜率
        for(int i=0;i<3;++i){
            int num=0;//胜利次数
            for(int j=1;j<=6;++j){//cout<<"@";
                for(int k=0;k<3;++k){
                    n2[k]=n[k];
                }
                n2[i]=j;

                if(n2[0]!=n2[1]&&n2[0]!=n2[2]&&n2[1]!=n2[2])ntype=1;
                else if(n2[0]==n2[1]&&n2[1]==n2[2])ntype=3;
                else ntype=2;

                sort(n2,n2+3);
                if(win(n2,a))++num;
            }

            if((double)num/6>ans)ans=(double)num/6;
        }

        printf("%.3f
",ans);
    }

    return 0;
}
View Code

1004、质方数

d.质数的平方命名为“质方数”。

距离一个正整数N最接近的质方数是多少?

s.打表,搜索即可。二分搜索都没用到,因为质方数就1000多个。。

c.

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
/*
素数筛选,存在小于等于MAXN的素数
prime[0]存的是素数的个数
*/
const int MAXN=11000;
int prime[MAXN+1];
void getPrime(){
    memset(prime,0,sizeof(prime));
    int i,j;
    for(i=2;i<=MAXN;++i){
        if(!prime[i])prime[++prime[0]]=i;
        for(j=1;j<=prime[0]&&prime[j]<=MAXN/i;++j){
            prime[prime[j]*i]=1;
            if(i%prime[j]==0)break;
        }
    }
}

int _L,_m;
int _search(int k){
    if(k<=prime[1])return 1;

    for(int i=2;i<=prime[0];++i){
        if(prime[i]==k)return i;
        if(prime[i]>k)return abs(prime[i-1]-k)<abs(prime[i]-k)?i-1:i;
    }
    return -1;
}

int main(){
    getPrime();
    int i;
    for(i=1;i<=prime[0];++i)
        prime[i]=prime[i]*prime[i];
    //cout<<prime[0]<<endl;
    //cout<<prime[prime[0]]<<endl;

    int T;
    int N;
    scanf("%d",&T);
    while(T--){
        scanf("%d",&N);
        printf("%d
",prime[_search(N)]);
    }
    return 0;
}
View Code

1005、ACM组队安排

d.

s.递推,

假设是第n 个人
它有三种组队方法
1.他自己组队--ans[n-1]
2.他和他之前的n-1个人中挑出一个和他组队--(n-1)*ans[n-2]
3.他和他之前的n-1个人中挑出两个和他组队--C(2,n-1)*ans[n-3]

c.

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

int main(){
    __int64 ans[25];
    ans[1]=1;
    ans[2]=2;
    ans[3]=5;
    for(int i=4;i<25;++i)
        ans[i]=ans[i-1]+(i-1)*ans[i-2]+(i-1)*(i-2)/2*ans[i-3];

    int n;
    while(~scanf("%d",&n)){
        if(n==0)break;
        printf("%I64d
",ans[n]);
    }
    return 0;
}
View Code

1006、逆袭指数

d.

s.暴力搜索即可

c.

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

int factor[1024],factor2[1024],factNum;

void dfs(int k,int n,int num){
    if(n%k==0){
        factor2[num]=k;
        dfs(k+1,n/k,num+1);
    }
    else if(num>factNum){
        factNum=num;
        for(int i=0;i<factNum;++i)
            factor[i]=factor2[i];
    }
}

int main(){

    int N;
    while(~scanf("%d",&N)){
        factNum=0;
        int k=sqrt(N)+1;
        for(int i=2;i<=k;++i)
            dfs(i,N,0);

        if(factNum==0){
            printf("1
");
            printf("%d
",N);
        }
        else{
            printf("%d
",factNum);
            for(int i=0;i<factNum-1;++i)
                printf("%d*",factor[i]);
            printf("%d
",factor[factNum-1]);
        }
    }
    return 0;
}
View Code

1007、油菜花王国

d.

s.并查集

c.

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

const int MAXN=1024;
const int MAXM=46;

int fi[MAXM];
bool vis[MAXN];
int sum[MAXN];

void f(){
    fi[0]=fi[1]=1;
    for(int i=2;i<MAXM;++i){
        fi[i]=fi[i-1]+fi[i-2];
    }
}

bool isfi(int n){
    for(int i=0;i<MAXM;++i)
        if(fi[i]==n)return true;
    return false;
}

int fa[MAXN];
int set_find(int d){
    if(fa[d]<0)return d;
    return fa[d]=set_find(fa[d]);
}

void set_join(int x,int y){
    vis[x]=true;
    vis[y]=true;
    x=set_find(x);
    y=set_find(y);
    if(x!=y){
        fa[x]=y;
        sum[y]+=sum[x];
    }
}

int main(){
    f();
    //cout<<fi[MAXM-1]<<endl;
    int n,m;
    int k;
    int u,v;

    while(~scanf("%d%d",&n,&m)){
        memset(vis,false,sizeof(vis));
        memset(fa,-1,sizeof(fa));
        memset(sum,0,sizeof(sum));

        for(int i=1;i<=n;++i){
            scanf("%d",&k);
            if(isfi(k))
                sum[i]=1;
        }
        for(int i=0;i<m;++i){
            scanf("%d%d",&u,&v);
            set_join(u,v);
        }

        int ma=sum[1];
        for(int i=2;i<=n;++i){
            if(sum[i]>ma)ma=sum[i];
        }
        printf("%d
",ma);
    }
    return 0;
}
View Code

1008、游乐场

d.

s.贪心:优先选费用小的

c.

#include<iostream>
#include<stdio.h>
#include<algorithm>

using namespace std;
int main(){
    int x[10005];
    int pi[10005];
    int T;
    int n,m,k;

    scanf("%d",&T);
    while(T--){
        scanf("%d%d%d",&n,&m,&k);
        for(int i=0;i<n;++i)
            scanf("%d",&x[i]);

        __int64 tsum=0;
        for(int i=0;i<m;++i){
            scanf("%d",&pi[i]);
            tsum+=x[pi[i]-1];
            x[pi[i]-1]=0;
        }

        if(k<tsum)printf("-1
");
        else{
            int tol=m;
            sort(x,x+n);
            for(int i=m;i<n;++i){
                if(tsum+x[i]>k){
                    break;
                }
                else{
                    tsum+=x[i];
                    ++tol;
                }
            }
            printf("%d
",tol);
        }

    }
    return 0;
}
View Code

相关推荐