第六届福建省大学生程序设计竞赛

比赛没打。。。

赛后花了2个多小时1A5道题,好激动啊。先补作业去了,一堆实验报告等着我。 o(╯□╰)o。 


A题链接:点我

题意:给你n个电池的电量(100为满)和你可以充的电量m,问最多可以充满几个电池。


签到题吧。


AC代码:

#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <stack>
#include <map>
#include <vector>
#define INF 0x3f3f3f3f
#define eps 1e-8
#define MAXN (100+10)
#define MAXM (100000)
#define Ri(a) scanf("%d", &a)
#define Rl(a) scanf("%lld", &a)
#define Rf(a) scanf("%lf", &a)
#define Rs(a) scanf("%s", a)
#define Pi(a) printf("%d\n", (a))
#define Pf(a) printf("%.2lf\n", (a))
#define Pl(a) printf("%lld\n", (a))
#define Ps(a) printf("%s\n", (a))
#define W(a) while(a--)
#define CLR(a, b) memset(a, (b), sizeof(a))
#define MOD 1000000007
#define LL long long
#define lson o<<1, l, mid
#define rson o<<1|1, mid+1, r
#define ll o<<1
#define rr o<<1|1
#define PI acos(-1.0)
using namespace std;
int a[MAXN];
int main()
{
    int t; Ri(t);
    W(t)
    {
        int n, m;
        Ri(n); Ri(m);
        for(int i = 0; i < n; i++)
            Ri(a[i]), a[i] = 100-a[i];
        sort(a, a+n);
        int ans = 0;
        for(int i = 0; i < n; i++)
        {
            if(m - a[i] >= 0)
                ans++;
            else
                break;
            m -= a[i];
        }
        Pi(ans);
    }
    return 0;
}



B题链接:点我

题意:给你两个圆,问你切线有多少条,无数条时输出-1。


思路:判断两圆位置,分类讨论即可。

相交,相切,相离,重合,内含。



AC代码:

#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <stack>
#include <map>
#include <vector>
#define INF 0x3f3f3f3f
#define eps 1e-8
#define MAXN (100000+10)
#define MAXM (100000)
#define Ri(a) scanf("%d", &a)
#define Rl(a) scanf("%lld", &a)
#define Rf(a) scanf("%lf", &a)
#define Rs(a) scanf("%s", a)
#define Pi(a) printf("%d\n", (a))
#define Pf(a) printf("%.2lf\n", (a))
#define Pl(a) printf("%lld\n", (a))
#define Ps(a) printf("%s\n", (a))
#define W(a) while(a--)
#define CLR(a, b) memset(a, (b), sizeof(a))
#define MOD 1000000007
#define LL long long
#define lson o<<1, l, mid
#define rson o<<1|1, mid+1, r
#define ll o<<1
#define rr o<<1|1
#define PI acos(-1.0)
using namespace std;
int dis(int x1, int y1, int x2, int y2){
    return (x1-x2)*(x1-x2)+(y1-y2)*(y1-y2);
}
int main()
{
    int t; Ri(t);
    W(t)
    {
        int x1, y1, r1;
        int x2, y2, r2;
        Ri(x1); Ri(y1); Ri(r1);
        Ri(x2); Ri(y2); Ri(r2);
        int d = dis(x1, y1, x2, y2);
        int l = abs(r1-r2)*abs(r1-r2);
        int r = (r1+r2)*(r1+r2);
        if(x1 == x2 && y1 == y2 && r1 == r2)
            printf("-1\n");
        else if(d == r)
            printf("3\n");
        else if(d == l)
            printf("1\n");
        else if(d >= l && d <= r)
            printf("2\n");
        else if(d > r)
            printf("4\n");
        else
            printf("0\n");
    }
    return 0;
}




C题链接:点我

题意:0-1背包问题,扩大了背包容量和物品重量而已。

思路:容量过大,转化下思路就好了。设置dp[i][j]为前i个物品获得价值为j时所需的最小容量。

状态转移 dp[i][j] = min(dp[i-1][j], dp[i][j-val[i]] + w[i])。优化掉一维就可以了。


AC代码:

#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <stack>
#include <map>
#include <vector>
#define INF 0x3f3f3f3f
#define eps 1e-8
#define MAXN (500+10)
#define MAXM (100000)
#define Ri(a) scanf("%d", &a)
#define Rl(a) scanf("%lld", &a)
#define Rf(a) scanf("%lf", &a)
#define Rs(a) scanf("%s", a)
#define Pi(a) printf("%d\n", (a))
#define Pf(a) printf("%.2lf\n", (a))
#define Pl(a) printf("%lld\n", (a))
#define Ps(a) printf("%s\n", (a))
#define W(a) while(a--)
#define CLR(a, b) memset(a, (b), sizeof(a))
#define MOD 1000000007
#define LL long long
#define lson o<<1, l, mid
#define rson o<<1|1, mid+1, r
#define ll o<<1
#define rr o<<1|1
#define PI acos(-1.0)
using namespace std;
int dp[10000];
int v[510], w[510];
int main()
{
    int t; Ri(t);
    W(t)
    {
        int N, W;
        Ri(N); Ri(W);
        int sumv = 0;
        for(int i = 0; i < N; i++)
        {
            Ri(w[i]); Ri(v[i]);
            sumv += v[i];
        }
        CLR(dp, INF); dp[0] = 0;
        for(int i = 0; i < N; i++)
            for(int j = sumv; j >= v[i]; j--)
                dp[j] = min(dp[j], dp[j-v[i]] + w[i]);
        for(int i = sumv; i >= 0; i--)
        {
            if(dp[i] <= W)
            {
                printf("%d\n", i);
                break;
            }
        }
    }
    return 0;
}



E题链接:点我

题意:给你n个介于(0和m的数),你可以将0变成任意一个介于1-m的数。问你最长连续序列的长度。0是不合法的。

比如说 2 6 5 3 4 就算是一个长度为5的连续序列。序列不按顺序也行。


思路:记录0的个数cnt,排序去重后,分成若干个连续的块。求出每个块的长度l和起点s,终点e。

问题就变成最多花费cnt连通若干个块,使得连通的块最长。

这样用dp思想,枚举最后的一个连通的块,对每个块i求出其最远的起点块p即(连通p-i花费的代价最多为cnt)。

这里需要二分,为了进行二分操作,需要先统计花费的前缀和 即连通前i个块花费的总代价。

dp的过程中维护下最大值就好了。过程中注意边界,因为所有数的范围是1-m。

时间复杂度O(nlogn)。


AC代码:


#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <stack>
#include <map>
#include <vector>
#define INF 0x3f3f3f3f
#define eps 1e-8
#define MAXN (100000+10)
#define MAXM (100000)
#define Ri(a) scanf("%d", &a)
#define Rl(a) scanf("%lld", &a)
#define Rf(a) scanf("%lf", &a)
#define Rs(a) scanf("%s", a)
#define Pi(a) printf("%d\n", (a))
#define Pf(a) printf("%.2lf\n", (a))
#define Pl(a) printf("%lld\n", (a))
#define Ps(a) printf("%s\n", (a))
#define W(a) while(a--)
#define CLR(a, b) memset(a, (b), sizeof(a))
#define MOD 1000000007
#define LL long long
#define lson o<<1, l, mid
#define rson o<<1|1, mid+1, r
#define ll o<<1
#define rr o<<1|1
#define PI acos(-1.0)
using namespace std;
struct Node{
    int s, e, l;
};
Node num[MAXN];
int top;
int rec[MAXN], used[MAXN];
int main()
{
    int t; Ri(t);
    W(t)
    {
        int n, m;
        Ri(n); Ri(m);
        int cnt = 0;
        int len = 1;
        for(int i = 1; i <= n; i++)
        {
            int a; Ri(a);
            if(a)
                rec[len++] = a;
            else
                cnt++;
        }
        int R;
        if(len != 1)
        {
            sort(rec+1, rec+len);
            R = 2;
            for(int i = 2; i < len; i++)
                if(rec[i] != rec[i-1])
                    rec[R++] = rec[i];
            sort(rec+1, rec+R);
            rec[R] = -1;
        }
        else
            R = 1;
        int sum = 1; top = 0;
        for(int i = 1; i <= R-1; i++)
        {
//            Pi(rec[i]);
            if(rec[i] != rec[i+1] - 1)
            {
                ++top;
                num[top].l = sum;
                num[top].e = rec[i];
                num[top].s = rec[i] - sum + 1;
                sum = 1;
            }
            else
                sum++;
        }
//        for(int i = 1; i <= top; i++)
//            printf("%d %d %d\n", num[i].s, num[i].e, num[i].l);
        used[1] = 0;
        for(int i = 2; i <= top; i++)
            used[i] = used[i-1] + num[i].s - num[i-1].e - 1;// Pi(used[i]);
        int ans = 0;
        for(int i = 1; i <= top; i++)
        {
            int v = used[i] - cnt;
            int p;
            if(cnt >= used[i])
                p = 1;
            else
                p = lower_bound(used, used+top+1, v) - used;
            //printf("---%d ", p);
            int have = num[i].e - num[p].s + 1;
            int cost = used[i] - used[p];
            if(cnt > cost)
            {
                int left = num[p].s - 1;
                int right = m - num[i].e;
                have += min(left + right, cnt - cost);
            }
            ans = max(ans, have);
            //Pi(ans);
        }
        if(ans == 0)
            ans = max(ans, min(cnt, m));
        Pi(ans);
    }
    return 0;
}



J题链接:点我

题意:给你两个队伍A和B,分别有n、m个人。现在要进行三次比赛来决定胜负,一场比赛两支队伍都要出一定的人数

Ai、Bi,若Ai >= Bi则A胜反之B胜。问你队伍A是否存在一种安排方案,使得队伍B无论怎样出人都会输掉比赛。


5min帮别人YY一个思路,没想到那货就这样AC了。 O__O "…

思路:把n分成三份,把剩余的部分均分给其中一份(余2就均分给其中两份)。判断最小的两份之和 + 2 是否小于等于 m。


AC代码:

#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <stack>
#include <map>
#include <vector>
#define INF 0x3f3f3f3f
#define eps 1e-8
#define MAXN (500+10)
#define MAXM (100000)
#define Ri(a) scanf("%d", &a)
#define Rl(a) scanf("%lld", &a)
#define Rf(a) scanf("%lf", &a)
#define Rs(a) scanf("%s", a)
#define Pi(a) printf("%d\n", (a))
#define Pf(a) printf("%.2lf\n", (a))
#define Pl(a) printf("%lld\n", (a))
#define Ps(a) printf("%s\n", (a))
#define W(a) while(a--)
#define CLR(a, b) memset(a, (b), sizeof(a))
#define MOD 1000000007
#define LL long long
#define lson o<<1, l, mid
#define rson o<<1|1, mid+1, r
#define ll o<<1
#define rr o<<1|1
#define PI acos(-1.0)
using namespace std;
int main()
{
    int t; Ri(t);
    W(t)
    {
        int n, m;
        Ri(n); Ri(m);
        int a = n / 3;
        int b = a, c = a;
        int yu = n % 3;
        if(yu == 1)
            a++;
        if(yu == 2)
            a++, b++;
        if(b + c + 2 <= m)
            printf("No\n");
        else
            printf("Yes\n");
    }
    return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值