2017广东工业大学程序设计竞赛决赛【解题报告】【待补全】

>

首先:
个人方面: 思路不清,代码能力太弱。好多题型都没见过。GG啊…………哎,还要再加强训练啊。

 Problem A 两只老虎

http://gdutcode.sinaapp.com/problem.php?cid=1057&pid=0
————————————————————————————————————————————
首先考虑对于假如一只老虎只有两个耳朵或一个尾巴 ,那么总老虎数就是a/2+b,但是一共只有c/4个老虎,那么多出来的就是正常老虎的个数。即a/2+b-c/4

int main(){
    int _,a,b,c;
    scanf("%d",&_);
    while(_--){
        scanf("%d%d%d",&a,&b,&c);
        a/=2;c/=4;
        printf("%d\n",a+b-c);
    }
    return 0;
}

Problem B 占点游戏
http://gdutcode.sinaapp.com/problem.php?cid=1057&pid=1
————————————————————————————————————————————
好吧,补题。这个不会…………GG

Problem C 爬楼梯
http://gdutcode.sinaapp.com/problem.php?cid=1057&pid=2
————————————————————————————————————————————

好吧,我看好多代码都是推出了转移过程F[I]=F[I-1]+F[I-2]+F[I-3];

我是先dfs出n个台阶的方法数的,之后把每一层的走法相乘取模即可。

#include <iostream>
#include <algorithm>
#define maxs 20020
#define mme(i,j) memset(i,j,sizeof(i))
#define pb(x) push_back(x)
#include <queue>
#define ll long long
#define mod 10007
#include <stdio.h>
using namespace std;
int wax[3]={1,2,3};
ll sum=0;
int was[21]={0,1,2,4,7,13,24,44,81,149,274,504,927,1705,3136,5768,10609,19513,35890,66012,121415};
void dfs(int n)
{
    if(n==0)
    {
        sum++;
        return;
    }
    int now;
    for(int i=0;i<3;i++)
    {
        now=n-wax[i];
        if(now>=0)
            dfs(now);
    }
}
int main()
{
    int n;
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        sum=1;
        int x;
        for(int i=1;i<n;i++)
        {
            scanf("%d",&x);
            sum=sum*(was[x]%mod)%mod;
        }
        cout<<sum%mod<<endl;
    }
    return 0;
}

Problem D 只有通过毁灭才能揭示真理
http://gdutcode.sinaapp.com/problem.php?cid=1057&pid=3
————————————————————————————————————————————
这个明白题意就能AC了

int main(){
    int _,a,b,c;
    scanf("%d",&_);
    while(_--){
        scanf("%d%d%d",&a,&b,&c);
        printf("%d\n",a*b+(a/30)*c);
    }
    return 0;
}

Problem E 倒水(Water)
http://gdutcode.sinaapp.com/problem.php?cid=1057&pid=4
————————————————————————————————————————————

其实这题贪心就好,
我们要最少的水杯,那就倍增的将若干个杯子变成一个就好了,
那么也就是说2x最后都能变成一个水杯, 这是不花费是最少的杯子个数
而我们要是最后的杯子个数<=k
那么只要最贪心的这个最小的两个2x 变成一个就好了,
那么就是不断的加上最小的一个2x,最后能将这两个凑成一个

暴力写就好了 时间上不会超过\logn的.

(其实就是一个树状数组更新的过程么。。


#define lowbit(x) (x&-x)

int a[N];
int cal(LL a){
    int num = 0;
    while(a){
        if(a&1) num++;
        a>>=1;
    }
    return num;
}
int main(){
    int _,k;
    LL n;
    scanf("%d",&_);
    while(_--){
        scanf("%lld",&n);
        scanf("%d",&k);
        LL ans = 0;
        while(cal(n)>k){
            ans+=lowbit(n);
            n+=lowbit(n);
        }

        printf("%lld\n",ans);
    }
    return 0;
}

Problem F tmk找三角
http://gdutcode.sinaapp.com/problem.php?cid=1057&pid=5
————————————————————————————————————————————

补题啊- - 这个不会。

Problem G 等凹数字
http://gdutcode.sinaapp.com/problem.php?cid=1057&pid=6
————————————————————————————————————————————
这道题最开始以为是一个数位dp,想在求区间回文数个数的代码上改一改 ,但是因为渣渣实在太菜,没有调出来,

快结束暴力处理了一下范围内所有等凹数字,发现只有180k+,
那么我们只要对区间进行二分就好了.。 好吧- -这题正解是数位DP…………

#include <bits/stdc++.h>
#define mme(i,j) memset(i,j,sizeof(i))
#define maxs 202002
#define ll long long
using namespace std;
int num[20];//存 n 每位上的数的。看n是否为回文
ll cnt;
ll ans[3*maxs],len;

void solve1(int n)
{
    if(n<10)
        return ;
    len=0;
    ll tmp=n;
    while(n) {

        num[len++]=n%10;
        tmp=tmp*10+n%10;
        n/=10;
    }
    if(num[0] != num[len-1])
        ans[++cnt]=tmp;
}

void solve2(int n)
{
    if(n<10)
        return;
    len=0;
    ll tmp=n;
    num[len++]=n%10;
    n/=10;
    while(n)
    {
        num[len++]=n%10;
        tmp=tmp*10+n%10;
        n/=10;
    }
    if(num[0] != num[len-1])
        ans[++cnt]=tmp;
}

void dfs(int now,int pre,int aim,int dig,bool state)// dfs(当前有几位,当前位数字,目标几位数,目标数,是否满足条件
{
    if(now>=aim)
    {
        if(state){ 找一半的数 3113 找前一半{

            solve2(dig);// 3113以31(point)13
            solve1(dig);// 3113以31 1(断点)3
        }
        return;
    }
    for(int i=pre;i>=0;i--) {
        dfs(now+1,i,aim,dig*10+i,i<pre || state);
    }
}

void init()
{
    for(int i=2;i<=9;i++)
        dfs(0,9,i,0,0);
    sort(ans+1,1+ans+cnt);
}

ll check(ll n)
{
    ll l=1,r=cnt,mid;
    while(l<=r)
    {
        mid=(l+r)>>1;
        if(ans[mid]>n)
            r=mid-1;
        else
            l=mid+1;
    }
    return r;
}

int main()
{
    init();
    int t;
    cin>>t;
    ll L,R;
    //fl<<"Ans is"<<"\n";
    while(t--)
    {
        cin>>L>>R;
        cout<<check(R)-check(L-1)<<endl;
    }
    return 0;
}

/*
593 9830
2184 3701
15710 29029
16970 25454
13156 28921
5657 12591
1069 31851
16750 18846
18967 24963
302 25831
28341 32254
9796 11191
6097 10278
17450 19209
5146 22333
1582 7360
2440 8622
11761 31353
7139 12959
10788 25510
766 5967
4855 16767
24103 28351
5035 22846
561 5694
19575 31129
2750 25141
16408 26630
8237 18903
575 28839
10001 10428
7303 15147
993 17356
*/

Problem H tmk买礼物
http://gdutcode.sinaapp.com/problem.php?cid=1057&pid=7
————————————————————————————————————————————
这道题被 Pending Rejudging了 但绝对能AC

51nod上有一个加强版的题目 题号1821

就是先升序排一下,在维护一个从0开始的变量,如果ans+1>=a[i] 的话就说明[0,ans+a[i]]元素都能凑出来

处理一下就好了

int a[N];
int main(){
    int _,n;
    scanf("%d",&_);
    while(_--){
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
        }
        sort(a+1,a+n+1);
        LL ans = 0;
        for(int i=1;i<=n;i++){
            if(ans+1>=a[i]) ans+=a[i];
            else  break;
        }

        printf("%lld\n",ans);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值