1. 程式人生 > >2017廣東工業大學ACM新生杯決賽

2017廣東工業大學ACM新生杯決賽

野生題解。

Problem A: junior97與The Flash

思路:這題精度有點苛刻了,導致姿勢不太好的小夥伴都過不了。我的做法是先求出中心到頂點的距離(即外接圓半徑,因為ax和角xoa已知),那麼求距離直接用餘弦定理就OK。


# include <bits/stdc++.h>
using namespace std;
const double pi = 3.141592653;
int n, m, a[1003];
double len;
double cal(int x, int y)
{
    int dis = abs(x-y);
    double ang = 360.0/n*dis*pi/180;
    double res = sqrt(2*len*len*(1-cos(ang)));
    return res;

}
int main()
{
    //freopen("3.in","r",stdin);
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&m);
        double tmp = 360.0/n/2*pi/180;
        len = 1/(2*sin(tmp));
        for(int i=0; i<m; ++i) scanf("%d",&a[i]);
        double sum = 0;
        for(int i=1; i<m; ++i)
            sum += cal(a[i-1], a[i]);
        printf("%.5f\n",sum);
    }
    return 0;
}

Problem B: 狗哥的肚子

思路:直接計算取最大的面積即可。
# include <bits/stdc++.h>
using namespace std;
const double pi = 3.14159;
int main()
{
    int T, n, x ,y;
    char c;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        double imax = 0;
        while(n--)
        {
            getchar();
            scanf("%c",&c);
            if(c == 'T')
            {
                scanf("%d%d",&x,&y);
                imax = max(imax, x*y*1.0/2);
            }
            else if(c == 'R')
            {
                scanf("%d%d",&x,&y);
                imax = max(imax, 1.0*x*y);
            }
            else
            {
                scanf("%d",&x);
                imax = max(imax, pi*x*x);
            }
        }
        printf("%.2f\n",imax);
    }
    return 0;
}

Problem C: 沒有題目背景的水題

思路:暴力O(n*n)可以過的。
# include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const double pi = 3.14159;
int a[5003];
int main()
{
    int T, n, k;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&k);
        for(int i=1; i<=n; ++i) scanf("%d",&a[i]);
        bool flag = 1;
        for(int i=1; i<=n&&flag; ++i)
        {
            int sum = 0;
            for(int j=i; j<=n&&flag; ++j)
            {
                sum += a[j];
                if(sum == k)
                {
                    printf("%d %d\n",i,j);
                    flag = 0;
                }
            }
        }
    }
    return 0;
}

Problem D: Gakki的疑問


思路:個數最少和字典序最小,顯然是貪心每次選做多1的,最後排下序輸出即可。
# include <bits/stdc++.h>
using namespace std;
int a[13], b[10]={0,1,10,100,1000,10000,100000,1000000};
int main()
{
    int T, n;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        int cnt = 0;
        while(n)
        {
            int x = n, k = 0;
            for(int i=1; i<=6&&x; ++i)
            {
                int y = x%10;
                if(y>0)
                {
                    n -= b[i];
                    k = k+b[i];
                }
                x /= 10;
            }
            a[cnt++] = k;
        }
        sort(a, a+cnt);
        printf("%d\n",cnt);
        for(int i=0; i<cnt; ++i) printf("%d%c",a[i],i==cnt-1?'\n':' ');
    }
    return 0;
}

Problem E: Joefery大佬的考核

思路:連線邊DG就發現三角形ADG的面積均為正方形和矩形面積的一半(以AD為底和以AG為底),那麼a*b%10007就是答案。這些題其實看到答案是整數的話可以猜一下公式。
# include <bits/stdc++.h>
using namespace std;
int main()
{
    int T, a, b;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&a,&b);
        printf("%d\n",a*b%10007);
    }
    return 0;
}

Problem F: 演算法的魅力


思路:簡單的容斥原理,先算5倍數的和,加上7倍數的和,減去5和7的最小公倍數(35)的倍數的和,就是等差數列求和。
# include <bits/stdc++.h>
using namespace std;
typedef long long LL;
LL n;
LL cal(LL x)
{
    LL r = n/x*x;//<=n裡最大的能被x整除的數。
    LL res = (x+r)*((r-x)/x+1)/2;
    return res;
}
int main()
{
    int T;

    scanf("%d",&T);
    while(T--)
    {
        scanf("%lld",&n);
        LL ans = cal(5)+cal(7)-cal(35);
        printf("%lld\n",ans);
    }
    return 0;
}

Problem G: 白色相簿的季節

思路:就是錯排問題,用遞推式。
# include <bits/stdc++.h>
using namespace std;
typedef long long LL;
LL a[20]={1, 0};
int main()
{
    int T, n;
    scanf("%d",&T);
    for(LL i=2; i<=18; ++i)
        a[i] = (a[i-1]+a[i-2])*(i-1);
    while(T--)
    {
        scanf("%d",&n);
        printf("%lld\n",a[n]);
    }
    return 0;
}

Problem H: 最小公倍數

思路:這題內榜AC率很尷尬。題面已經暗示了公有的倍數中最小的一個 ,直接從小到大列舉答案X,如果X能被>=K個數整除,它肯定就是最小公倍數了,答案範圍很親民,都不用線篩那樣打表了。
# include <iostream>
# include <cstdio>
using namespace std;
int a[103];
int main()
{
    int T, n, k;
    scanf("%d",&T);
    while(T--)
    {
        int ans;
        scanf("%d%d",&n,&k);
        for(int i=0; i<n; ++i) scanf("%d",&a[i]);
        for(int i=1; i<=1000; ++i)
        {
            int cnt = 0;
            for(int j=0; j<n; ++j)
                if(i%a[j]==0)
                    ++cnt;
            if(cnt >= k)
            {
                ans = i;
                break;
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}

Problem I: 狗哥的日常

思路:......
# include <bits/stdc++.h>
using namespace std;
int main()
{
    int T, n;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        while(n--)
            puts("Rua");
        if(T) puts("");
    }
    return 0;
}

Problem J: csjhl和潮汕煎蠔烙

思路:實在不會列舉所有情況都能過了。深搜一下即可。
# include <bits/stdc++.h>
using namespace std;
int a[6], ans;
void dfs(int num, int id)
{
    if(id == 6)
    {
        ans += num==24;
        return;
    }
    dfs(num+a[id], id+1);
    dfs(num-a[id], id+1);
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        ans = 0;
        for(int i=1; i<=5; ++i) scanf("%d",&a[i]);
        dfs(a[1], 2);
        printf("%d\n",ans);
    }
    return 0;
}

Problem K: 這題有點難

思路:c可以整除a和b的最大公因數就行了,具體搜尋“擴充套件歐幾里得”相關知識。
# include <bits/stdc++.h>
using namespace std;
int main()
{
    int T, a, b, c, q;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d%d",&a,&b,&q);
        int g = __gcd(a,b);
        while(q--)
        {
            scanf("%d",&c);
            printf(c%g==0?"Yes\n":"No\n");
        }
    }
    return 0;
}