2017广东工业大学ACM新生杯初赛

真想再体验一把新生杯。(部分题解)

Problem A: Chinese Remainder Theorem

思路:中国剩余定理,套个板子就行了,注意输入的数据要去重。

# include <iostream>
# include <cstdio>
# include <cstring>
using namespace std;
typedef long long LL;
const int maxn = 20;
int n;
LL m[maxn], r[maxn];
int vis[20][20];
LL extend_Euclid(LL a, LL b, LL &x, LL &y)//扩展欧几里得。
{
    if(b==0)
    {
        x = 1; y = 0;
        return a;
    }
    LL r = extend_Euclid(b, a%b, y, x);
    y -= a/b*x;
    return r;
}
LL China()
{
    LL M = 1, ans = 0;
    for (int i = 0; i < n; ++i) M *= m[i];
    for(int i = 0;i < n;i++)
    {
        LL N = M/m[i];
        LL x, y;
        extend_Euclid(N, m[i], x, y);
        x = (x%m[i] + m[i]) % m[i];
        ans = ((ans+r[i]*N%M*x%M)%M + M) % M ;
    }
    return (M+ans%M)%M;
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        int i,cnt=0;
        memset(vis, 0, sizeof(vis));
        for(i=0; i<n; ++i)
        {
            LL tx, ty;
            scanf("%lld%lld",&tx,&ty);
            if(!vis[tx][ty] == 1)
            {
                vis[tx][ty] = 1;
                r[cnt] = tx;
                m[cnt++] = ty;
            }
        }
        n = cnt;
        LL ans = China(), f=1;
        for(int i=0; i<n; ++i)
        {
            if(ans%m[i] != r[i])
            {
                f = 0;
                puts("IMPOSSIBLE");
                break;
            }
        }
        if(f) printf("%lld\n",ans);
    }
    return 0;
}


Problem B: AC的概率

思路:根据同余定理,(a+b)%6==0,有(a%6+b%6)%6 == 0,将每个数先取模6,同时记录到数组b上,扫一遍即可。

# include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+30;
int a[maxn];
int main()
{
    int t, n;
    scanf("%d",&t);
    while(t--)
    {
        int b[7]={0};
        scanf("%d",&n);
        double tot = (double)n*(n-1)/2, sum=0;
        for(int i=0; i<n; ++i)
        {
            scanf("%d",&a[i]);
            a[i] %= 6;
            if(a[i] == 0) sum += b[a[i]];
            else sum += b[6-a[i]];
            ++b[a[i]];
        }
        printf("%.6f\n",sum*1.0/tot);
    }
    return 0;
}

Problem D: 好难啊

思路:目测是CF Div2的一道题,先不考虑最后一行和最后一列,任意填充前(n-1)*(m-1)个格,那么最后一行和最后一列显然可以填上1或-1使得每行每列都等于k,那么右下角那个格子呢?设前(n-1)*(m-1)个格乘积为sum,对于列来说,右下角填上A=k^(n-1)*sum,对于行来说右下角填上B=k^(m-1)*sum。那么显然如果k=-1,且n和m奇偶性不同时A不等于B,其余情况都能满足。

# include <iostream>
# include <cstdio>
# include <cstring>
using namespace std;
typedef long long LL;
int main()
{
    LL n, m, k;
    while(~scanf("%lld%lld%lld",&n,&m,&k))
    {
        if((n&1) != (m&1) && k == -1)
            puts("Orz");
        else puts("O(^_^)O~~");
    }
    return 0;
}

Problem E: 工会首领yjl

思路:贪心,先按Q值排序,所有人得到ceil(Q/2)元,剩下的钱倒着派发,Q值大的先派发。

# include <iostream>
# include <cstdio>
# include <cstring>
# include <algorithm>
using namespace std;
typedef long long LL;
struct node
{
    int x, id;
}a[103];
int ans[103];
bool cmp(node a, node b)
{
    return a.x < b.x;
}
int main()
{
    int n, m;
    while(~scanf("%d%d",&n,&m))
    {
        for(int i=0; i<n; ++i)
        {
            scanf("%d",&a[i].x);
            a[i].id = i;
        }
        sort(a, a+n, cmp);
        int sum = 0, sum2=0;
        for(int i=0; i<n; ++i)
        {
            int tmp = (int)ceil(a[i].x/2.0);
            ans[a[i].id] = tmp;
            sum += tmp;
            sum2 += a[i].x;
        }
        if(sum > m || sum2 < m)
        {
            puts("gg");
            continue;
        }
        int rest = m-sum;
        for(int i=n-1; i>=0; --i)
        {
            int id = a[i].id;
            int imin = min(rest, a[i].x-ans[id]);
            if(i < n-1) imin = min(imin, ans[a[i+1].id]-ans[id]);
            ans[id] += imin;
            rest -= imin;
        }
        for(int i=0; i<n; ++i)
            printf("%d ",ans[i]);
        puts("");
    }
    return 0;
}

Problem F: 位数是多少?

思路:计算一个数x的位数是log10(x)+1,计算log10(a^b)+1可以化为b*log10(a)+1。

# include <iostream>
# include <cstdio>
# include <cstring>
# include <algorithm>
using namespace std;
typedef long long LL;
using namespace std;
int main()
{
    int x, y, t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&x,&y);
        printf("%d\n",(int)(y*log10(x))+1);
    }
    return 0;
}

Problem G: 一道简单的题目


思路:就是直接做,但是数据我故意加了一堆1进去...所以预处理每个1右边的首个非1数的位置即可,不然会超时。

# include <iostream>
# include <cstdio>
# include <cstring>
using namespace std;
const int maxn = 1e5+30;
int a[maxn], r[maxn];
int main()
{
    int n, q, L, R, K;
    while(~scanf("%d%d",&n,&q))
    {
        memset(r, 0, sizeof(r));
        memset(a, 0, sizeof(a));
        for(int i=1; i<=n; ++i) scanf("%d",&a[i]);
        r[n] = n+1;
        for(int i=n-1; i>=1; --i)
        {
            if(a[i+1] == 1) r[i] = r[i+1];
            else r[i] = i+1;
        }
        while(q--)
        {
            scanf("%d%d%d",&L,&R,&K);
            for(int i=L; i<=R; i=r[i])
            {
                K /= a[i];
                if(K==0) break;
            }
            printf("%d\n",K);
        }
    }
    return 0;
}

Problem H: 一棵二叉树

思路:子节点除以二就是父节点的编号,一直往上除直到一存到数组。比较两个点的公共祖先最大那个。

#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
typedef long long LL;

LL arr[500];

int main()
{
    int T;
    LL a,b;
    scanf("%d",&T);
    while(T--){
        scanf("%lld%lld",&a,&b);
        memset(arr,0,sizeof(arr));
        int tmp=0;
        while(a){
            arr[tmp++]=a;
            a>>=1;
        }
        while(b){
            arr[tmp++]=b;
            b>>=1;
        }
        sort(arr,arr+tmp);
        for(int i=tmp-1;i;--i)
            if(arr[i]==arr[i-1]){
                printf("%lld\n",arr[i]);
                break;
            }
    }
    return 0;
}

后面的先留坑

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值