山东省第八届ACM程序设计竞赛----其中七道题的题解

98 阅读3分钟

雨还下个不停,就在实验室打打题,活动活动脑子。

\

山东省第八届ACM程序设计竞赛。国庆节重现赛。

A题是威佐夫博弈+Nim游戏博弈论。若了解这两个博弈游戏的话,超级简单的一道题。

C题烟火爆炸,难在求组合数,需要用到逆元。其中我代码中的求法可以提取出来当板子用。

F题判段离散数学中的一个条件命题是否正确。难点是判断浮点数a / b是否为整数。iff a % b = 0

G题快速幂

I题同余定理,边乘边取余。

J题数组展开,弄个后缀和。贪心一下,1A哈

K题01背包。先做扣分快,容易做的题。两者综合考虑。

\

下面是代码。写得很粗糙。。。

A题 (威佐夫博弈百度百科

#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
//#define TEST
int main()
{
#ifdef TEST
    freopen("data.in", "r", stdin);
    freopen("data.out", "w", stdout);
#endif
    //ios::sync_with_stdio(false);
    int T;
    scanf("%d", &T);
    while(T-- > 0) {
        int n;
        scanf("%d", &n);
        int a[50];
        for (int i = 0; i < n; ++i) {
            scanf("%d", a + i); 
        }
        if(n == 2) {
            if(a[0] > a[1]) {
                swap(a[0], a[1]);
            }
            if(floor((a[1]-a[0]) * ((sqrt(5.0)+1.0)/2.0) ) != a[0]){
                printf("Sherlock\n");
            }
            else {
                puts("Watson");
            }
        }
        else {
            int k = 0;
            for (int i= 0; i < n; ++i) {
                k ^= a[i];
            }
            if(k == 0) {
                puts("Watson");
            }
            else {
                puts("Sherlock");
            }
        }
    }
 
    return 0;
}


\

C题

#include <cstdio> 
const int mod = 1e9 + 7;
typedef long long LL;
const int N = 1e5 + 7;
LL fac[N];
void factor() {
    fac[0] = fac[1] = 1;
    for (int i= 2; i < N; ++i) {
        fac[i] = fac[i - 1] * i % mod;
    }
}
LL quick_pow(LL a, LL n) {
    LL res = 1;
    while(n > 0) {
        if(n & 1) res = res * a % mod;
        a = a * a % mod;
        n >>= 1; 
    }
    return res;
}
LL C(LL n, LL m) {
    return fac[n] * quick_pow(fac[n - m], mod - 2) % mod 
          * quick_pow(fac[m], mod - 2) % mod; 
}
int main()
{
    factor();
    int n, t, w;
    while(~scanf("%d%d%d", &n, &t, &w)) {
        LL res = 0;
        for (int i = 0; i < n; ++i) {
            LL x, val;
            scanf("%lld%lld", &x, &val);
            LL k = w - x >= 0 ? w - x : x - w;
            if((k & 1) == (t & 1) && k <= t) //距离 时间 同奇共偶。且距离小于时间 * 1 
                res = (res + (val * C(t, (k + t) >> 1)) % mod) % mod;
        }
        printf("%lld\n", res);
    }
     
    return 0;
}


F题

#define _CRT_SECURE_NO_WARNINGS
#include <cstdio>
#include <iostream>
#include <iomanip>
#include <cstring>
#include <string>
#include <algorithm>
#include <climits>
#include <cmath>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <ctime>
#include <cstdlib>
#include <iterator>
using namespace std;
const double eps = 1e-8; 
//#define TEST
int main()
{
#ifdef TEST
    freopen("data.in", "r", stdin);
    freopen("data2.out", "w", stdout);
#endif
    //ios::sync_with_stdio(false);
    int T;
    scanf("%d", &T);
    while(T-- > 0) {
        int a, b, c;
        scanf("%d%d%d", &a, &b, &c);
        if(a == 0) {
            if(b == 0) {
                if(c != 0) puts("YES"); //if不成立 
                else puts("NO"); //x可能不是int 
            }
            else {//有一个解 
                if(c % b == 0) puts("YES"); //假设成立 
                else puts("NO"); //不成立 
            }
            continue;
        }
        double delta = b * b - 4 * a * c;
        if(delta < 0) { //二次方程,无解。if不成立 
            puts("YES");
            continue;
        }
        int tmp = sqrt(delta);
        delta = sqrt(delta);
        //printf("delta = %lf\n", delta);
        double x1 = (-b + delta) / (2.0 * a);
        double x2 = (-b - delta) / (2.0 * a);
        //printf("x1 = %d, x2 = %d\n", x1, x2); 
        if(delta - tmp < eps &&//浮点数相等 
           (-b + tmp) % (2 * a) == 0 && 
           (-b - tmp) % (2 * a) == 0) {
            puts("YES");
        }
        else  puts("NO");
    }
 
    return 0;
}


G题

#define _CRT_SECURE_NO_WARNINGS
#include <cstdio>
#include <iostream>
#include <iomanip>
#include <cstring>
#include <string>
#include <algorithm>
#include <climits>
#include <cmath>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <ctime>
#include <cstdlib>
#include <iterator>
using namespace std;
const int mod = 1e9 + 7; 
long long pow_mod(long long b, long long n) {
    long long res = 1;
    while(n) {
        if(n & 1) res = (res * b) % mod;
        b = b * b % mod;
        n >>= 1;
    }
    return res;
}
//#define TEST
int main()
{
#ifdef TEST
    freopen("data.in", "r", stdin);
    freopen("data.out", "w", stdout);
#endif
    //ios::sync_with_stdio(false);
    long long n, m;
    while(~scanf("%lld%lld", &n, &m)) {
        long long res = 0;
        for (long long i = 1; i <= n; ++i) {
            res = (res + pow_mod(i, m)) % mod; 
        }
        printf("%lld\n", res);
    }
 
    return 0;
}


I题

#define _CRT_SECURE_NO_WARNINGS
#include <cstdio>
#include <iostream>
#include <iomanip>
#include <cstring>
#include <string>
#include <algorithm>
#include <climits>
#include <cmath>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <ctime>
#include <cstdlib>
#include <iterator>
using namespace std;
const int N = 1007;
char str[N]; 
//#define TEST
int main()
{
#ifdef TEST
    freopen("data.in", "r", stdin);
    freopen("data.out", "w", stdout);
#endif
    //ios::sync_with_stdio(false);
    while(~scanf("%s", str)) {
        int len = strlen(str);
        int res = 0;
        for (int i = 0; i < len; ++i) {
            res = (res * 10 + str[i] - '0') % 3;
        } 
        if(res == 0) puts("0");
        else puts("1");
    }
 
    return 0;
}


J题

#define _CRT_SECURE_NO_WARNINGS
#include <cstdio>
#include <iostream>
#include <iomanip>
#include <cstring>
#include <string>
#include <algorithm>
#include <climits>
#include <cmath>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <ctime>
#include <cstdlib>
#include <iterator>
using namespace std;
const int N = 100007;
int st[N];
long long suf[N];
struct Node {
    int val, cnt;
    bool operator < (const Node &tmp) const {
        return val < tmp.val;
    }
}a[1007];
//#define TEST
int main()
{
#ifdef TEST
    freopen("data.in", "r", stdin);
    freopen("data.out", "w", stdout);
#endif
    //ios::sync_with_stdio(false);
    int n;
    while (~scanf("%d", &n)) {
        for (int i = 0; i < n; ++i)  scanf("%d", &a[i].val);
        for (int i = 0; i < n; ++i) scanf("%d", &a[i].cnt);
        sort(a, a + n);
        int cur = 0;
        for (int i = 0; i < n; ++i) {
            while (a[i].cnt-- > 0) st[cur++] = a[i].val;
        }
        suf[cur] = 0;
        int start = 0;
        for (int i = cur - 1; i >= 0; --i) {
            suf[i] = st[i] + suf[i + 1];//后缀
            if (suf[i] <= 0) {
                start = i + 1;
                break;
            }
        }
        //printf("start = %d\n", start);
        long long res = 0;
        for (int i = start, j = 1; i < cur; ++i, ++j) {
            res += j * st[i];
        }
        printf("%lld\n", res);
    }
 
    return 0;
}


K题

#include <cstdio>
#include <iostream>
#include <iomanip>
#include <cstring>
#include <string>
#include <algorithm>
#include <climits>
#include <cmath>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <ctime>
#include <cstdlib>
#include <iterator>
using namespace std;
const int N = 2007;
struct ABCD {
    int a, c, d;
    double v; //正比于时间c,反比于降率d
    bool operator < (const ABCD& tmp) const {
        return v < tmp.v; //起初忘了写return 
    }
}t[N];
int dp[5007];
int main()
{
    int n, T;
    while(~scanf("%d%d", &n, &T)) {
        for (int i = 0; i < n; ++i) scanf("%d", &(t[i].a));
        for (int i = 0; i < n; ++i) scanf("%d", &(t[i].d));
        for (int i = 0; i < n; ++i) {
            scanf("%d", &(t[i].c));
            t[i].v = t[i].c / (double)t[i].d;
        }
        sort(t, t + n);
        memset(dp, 0, sizeof dp); //dp[time] = grade
        int maxV = 0;
        for (int i = 0; i < n; ++i) {
            for (int j = T; j >= t[i].c; --j) {
                dp[j] = max(dp[j], dp[j - t[i].c] + t[i].a - t[i].d * j);
                maxV = max(maxV, dp[j]);
            } 
        }
        printf("%d\n", maxV); 
    }
 
    return 0;
}


\

\