HDU 11.29 新生赛题解

彩笔大三了还去打hdu大一的比赛,看各路大神一小时内各种AK,彩笔多花了一倍的时间才做完。06不是admin及时回答了提问估计要卡到比赛结束。附上题解:

A.搬砖

这个题按照题目逆序来感觉不好做啊。然后想想可以写成递推的形式。对于x来言,如果x是奇数,那么dp[x]=dp[x/2]+dp[x/2+1]+1...否则就是dp[x/2]的2倍...算是简单递推吧..

#include<bits/stdc++.h>
using namespace std;
int dp[10000007];
int main()
{
    dp[1]=0;dp[2]=0;
    for(int i=3;i<=10000000;i++)
    {
        if(i%2)
            dp[i]+=dp[i/2+1]+dp[i/2]+1;
        else
            dp[i]+=2*dp[i/2];
    }
    int t;
    cin>>t;
    while(t--)
    {
       int n;
       scanf("%d",&n);
       printf("%d\n",dp[n]);
    }
    return 0;
}


B.投币洗衣机

简单模拟题..按照题意来就好了。

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int n,a,b,c;
    while(scanf("%d %d %d %d",&n,&a,&b,&c)!=EOF)
    {
        int sum=0,ans=0;
        int v;
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&v);
            sum+=v;
            if(sum>=a&&sum<b)
            {
                ans+=2;
                sum=0;
            }
            else if(sum>=b&&sum<c)
            {
                ans+=3;
                sum=0;
            }
            else if(sum>=c)
            {
                ans+=4;
                sum=0;
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}

C.玩骰子

概率系列一直是弱项,看了半天才明白。就是如果直接可以赢那么概率就是1,然后就是可以换任意一个的点数,那么我们枚举三个骰子分别被更换点数后获胜的概率,取最大就好了,因为这个人比较聪明...

#include<bits/stdc++.h>
using namespace std;
#define ll long long
int T;
int b[10];
int    jiance(int x, int y, int z){
    if(x == y && y == z &&x == z) return 3;
    else if(x == y||y == z || x == z) return 2;
    else return 1; 
}
pair<int, int> zhao2(int x, int y, int z){
    if(x == y) return make_pair(x, z);
    if(y == z) return make_pair(y, x);
    if(x == z) return make_pair(x, y);
}
int a[10];
bool jiance(int *b){
        for(int i=1; i<=6; i++) a[i] = b[i];
        sort(a+1, a+4);
        sort(a+4, a+7);
        int flag1 = jiance(a[1], a[2], a[3]);
        int flag2 = jiance(a[4], a[5], a[6]);        
        if(flag1 > flag2){
            return true;
        }
        else if(flag1 == flag2){
            if(flag1 == 3&&a[1] > a[4])return true; 
            else if(flag1 == 2){
                pair<int, int> t1 = zhao2(a[1], a[2], a[3]);
                pair<int, int> t2 = zhao2(a[4], a[5], a[6]);
                if(t1.first > t2.first) return true; 
                else if(t1.first == t2.first && t1.second > t2.second) return true; 
            }    
            else if(flag1 == 1){
                int flag = 0;
                if(a[6] > a[3]) flag = 1;
                else if(a[6] == a[3]){
                    if(a[5] > a[2]) flag = 1;
                    else if(a[5] == a[2]){
                        if(a[4] >= a[1]) flag = 1;
                        else flag = -1;
                    }
                    else flag = -1;
                }
                else flag = -1;
                if(flag == -1) return true;
            }
        }
        return false;
}
int main(){
    cin>>T;
    while(T--){
        for(int i=1; i<=6; i++) scanf("%d", &b[i]);
        bool res = jiance(b);
        int ans = 0;
        double rrr = 0;
        if(res) printf("1.000\n");
        else{
            for(int i=1; i<=3; i++){
                ans = 0;
                for(int j=1; j<=6; j++){
                    int tmp = b[i];
                    b[i] = j;
                    if(jiance(b)){
                        ans ++;
                    }
                    b[i] = tmp; 
                }
                rrr = max(rrr, ans*1.0/6);
            }
            printf("%.3f\n", rrr);
        }
    }
    return 0;
}

D.质方

这个题范围10^8,所以我们打表出10^5以内的就可以了,10^4不太稳...因为万一大于10^8的离得最近怎么办...

然而我第一次用了二分WA了..不知道为啥,然后我换暴力过了- -真是太弱了。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
int ss[100007],ssb[100007];
int sscnt;
void db()
{
    sscnt=0;
    memset(ss,0,sizeof(ss));
    ss[1]=1;
    for(int i=2;i<=100000;i++)
    {
        if(ss[i]==0)
        {
            ssb[sscnt++]=i;
            for(int j=i+i;j<=100000;j+=i)
                ss[j]=1;
        }
    }
}
int main()
{
    db();
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n;
        scanf("%d",&n);
        ll ans=100000000000;
        for(int i=0;i<sscnt;i++)
        {
            ll tmp=(ll)ssb[i]*ssb[i];
            if(abs(tmp-(ll)n)<abs(ans-(ll)n))
                ans=tmp;
        }
        printf("%lld\n",ans);
    }
    return 0;
}
E.ACM组队安排

高中排列组合知识,弱打表过的...附上递推关系,k[i]为i个人组队情况综述。

k[i]=k[i-1]+k[i-2]*(i-1)+k[i-3]*(i-1)*(i-2)/2。

k[i-1]:新加的第i个人自己一队,其他人按照以前的方式组队

k[i-2]*(i-1):第i人与前i-1人中跳出一人组队,剩下的参考i-2人的组队

k[i-3]*(i-1)*(i-2)/2:第i人与前i-1人挑出2人组队,剩下的按照i-3人组队情况。

这个题就不上代码了。

F.逆袭指数

这个题的正确题意就是找出n最多有多少个连续的因子,而且这些因子相乘后的结果也是n的因子。

题意不明朗一直WA。然而get到正确题意就AC了。

通过种种方法我们可以得知n的因子数不会超过5000...直接暴力就好了。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
int n;
int yz[200000],ss;
void fj(int n)
{
    ss=0;
    yz[ss++]=n;
    int m=sqrt(n);
    for(int i=2; i<=m; i++)
    {
        if(n%i==0)
        {
            yz[ss++]=i;
            if(i*i!=n)
                yz[ss++]=n/i;
        }
    }
}
int main()
{
    while(scanf("%d",&n)!=EOF)
    {
        if(n==0)
        {
            printf("1\n0\n");
            continue;
        }
        fj(n);
        sort(yz,yz+ss);
        int len=1,ans=0;
        for(int i=0; i<ss; i++)
        {
            int now=yz[i],tmp=1;
            ll sum=yz[i];
            for(int j=i+1;j<ss;j++)
            {
                if(yz[j]==yz[j-1]+1&&n%(sum*yz[j])==0)
                {
                    tmp++;
                    sum=sum*yz[j];
                }
                else
                    break;
            }
            if(tmp>len)
            {
                len=tmp;
                ans=i;
            }
        }
        printf("%d\n%d",len,yz[ans]);
        for(int i=ans+1;i<ans+len;i++)
        {
            printf("*%d",yz[i]);
        }
        printf("\n");
    }
    return 0;
}
G.油菜花王国

简单并查集...完全不用考虑题目说的重边...刚开始写错判断条件过样例了还傻逼的WA了一发。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
int f[1234],r[1234];
ll fb[70];
int finde(int x)
{
    if(f[x]!=x)
        return f[x]=finde(f[x]);
    return x;
}
int main()
{
    fb[1]=1,fb[2]=2;
    for(int i=3;i<=50;i++)
    {
        fb[i]=fb[i-1]+fb[i-2];
    }
    int n,m;
    ll c;
    while(scanf("%d %d",&n,&m)!=EOF)
    {
        for(int i=1;i<=n;i++)
        {
            f[i]=i;
        }
        for(int i=1;i<=n;i++)
        {
            int j;
            scanf("%lld",&c);
            for(j=1;j<=50;j++)
                if(c<=fb[j]) break;
            if(c==fb[j])
                r[i]=1;
            else
                r[i]=0;
        }
        int u,v;
        for(int i=0;i<m;i++)
        {
            scanf("%d %d",&u,&v);
            int x=finde(u);
            int y=finde(v);
            if(x!=y)
            {
                f[x]=y;
                r[y]+=r[x];
            }
        }
        int ans=0;
        for(int i=1;i<=n;i++)
        {
            if(f[i]==i)
                ans=max(ans,r[i]);
        }
        printf("%d\n",ans);
    }
    return 0;
}

H.游乐场

简单贪心,先把m个选择的搞定,剩下的贪心选择就就好了,注意不要重复选择某个项目....

#include<bits/stdc++.h>
using namespace std;
#define ll long long
struct node
{
    int c,x;
}s[20000];
int cmp(node a,node b)
{
    return a.x<b.x;
}
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int n,m,k;
        scanf("%d %d %d",&n,&m,&k);
        int ans=0,p;
        for(int i=0;i<n;i++)
        {
            scanf("%d",&s[i].x);
            s[i].c=0;
        }
        for(int i=0;i<m;i++)
        {
            scanf("%d",&p);
            if(k>=s[p-1].x)
            {
                k-=s[p-1].x;
                s[p-1].c=1;
                ans++;
            }
        }
        if(ans<m)
        {
            printf("-1\n");
            continue;
        }
        sort(s,s+n,cmp);
        for(int i=0;i<n;i++)
        {
            if(s[i].c==1) continue;
            if(k<s[i].x) break;
            k-=s[i].x;
            ans++;
        }
        printf("%d\n",ans);
    }
    return 0;
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值