码迷,mamicode.com
首页 > 其他好文 > 详细

SCU集训队第三次周赛记录

时间:2015-04-26 09:21:07      阅读:148      评论:0      收藏:0      [点我收藏+]

标签:

A题(Win or Freeze)(博弈&数论)

  • 题目大意:对于1个数q,a和b两个人参与游戏,每一轮只能把q分解成q的所有因子中(且当一个人来分的时候他用的是最优决策),不是1和本身的因子,当其中一个人面对的数无法再被分解的时候该人获胜。
  • 数论知识补充:
    算术基本定理:一个大于x的自然数能被唯一确定的分解为有限个质数的乘积:

    x=pa11pa22pa33...pann
    这些质数都是这个数的质因子,且质数的质因子就是它本身。

  • 解题思路:
    1.考虑到q为1或质数是,显然a获胜,直接打印1,0。
    2.然后考虑q的非本身的质因子个数:如果质因子个数大于等于3个,那表示其中任意两个质因子的乘积小于q,且为q的一个合数(质数只有它本身一个质因子)因子(根据算术基本定理易得),这种情况下a只需将q分解成任意两个质因子之积x(这里考虑到算术基本定理相逆的情况,确定的质数序列的乘积为唯一确定的一个数,且这个数的因子也必定是这些质数序列),那么b只能把x分解成两个质数之一,a必胜。
    3.最后考虑q的非本身质数因子为2,那么这个数所有的因子就是这两个质因子【因为这两个数的乘积等于q,不可能有其它合数因子(一个数的合数因子,都是它的质数因子相乘得到的,而这个数的质数因子相乘只有得到它本身一个结果)】,无论a选那一个都是b稳赢。

  • 心得:这个题看了半天,所有单词都查了,就是读不懂题意。然后赛后理解了题意也不知道怎么做,因为不知道算术基本定理。

#include <cstdio>
#include <iostream>
using namespace std;
typedef long long int LL;
const int M=1009,INF=0x3ffffff;

bool isprime(LL x) {
    for(LL i = 2; i * i <= x; i++) if(x % i == 0) return false;
    return x > 1;  //排除小于等于1的情况
}

int main(void) {
    LL q;
    scanf("%I64d", &q);
    if(q == 1 && isprime) cout << "1" << endl << "0" << endl;
    else {
        int n = 0, f, s;
        for(LL i = 2; i * i <= q; i++) {
            if(q % i == 0) {  //如果i是q的因子就看i是否是质数
                q /= i;
                if(n == 0){f = i; i--;}
                if(n == 1) {s = i; i--;}
                if(n == 2) break;
                n++;
            }
        }
        if(n == 2) cout << 1 << endl << s * f << endl;
        else cout << 2 << endl;
    }
    return 0;
}

B题(Coderforces 148B)(模拟):
在纸上写好伪代码,考虑周全了,交上去,一次ac无它纯模拟。不要惧怕模拟题,只要仔细一次过是可以的。
代码:

#include <cstdio>
#include <iostream>
using namespace std;
typedef long long int LL;
const int M=100009,INF=0x3fffffff;
double vp, vd, pp, pd, t, f, c;

int main(void) {
    cin >> vp >> vd >> t >> f >> c;
    if(vd <= vp) cout << "0" << endl;
    else {
        double x = ((t *vp)/(vd - vp)) * vd;
        if(x >= c) cout << "0" << endl;
        else {
            int ans = 0;
            while(true) {
                ans++;
                double d = ((x / vd) * 2 + f) * vp;
                x = (d / (vd - vp)) * vp + x + d;
                if(x >= c) {cout << ans << endl; break;}
            }
        }
    }
    return 0;
}

C题(贪心)
是一个均分问题,但是有人数最多相差一的限制,使其简单了。如果没有人数限制,就可转化为背包容量为总数一半的01背包来做,寻找最接近一半的值。
代码:

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
typedef long long int LL;
const int M=100009,INF=0x3fffffff;
int n, str[M],a ,b;
pair<int, int> v[M];

int main(void) {
    cin >> n;
    for(int i = 0; i < n; i++){cin >> v[i].first; v[i].second = i + 1;}
    sort(v, v + n);
    int q = 0, p = n - 1, x = 0, y = 0;
    while(p >= q) {
        if(p == q) {
            if(a <= b){str[v[p].second] = 1; x++;}
            else y++;
            break;
        }
        if(a >= b) {
            a += v[q].first;
            str[v[q].second] = 1;
            b += v[p].first;
            p--;
            q++;
        }
        else {
            b += v[q].first;
            str[v[p].second] = 1;
            a += v[p].first;
            p--;
            q++;
        }
        x++;
        y++;
    }
    cout << x << endl;
    bool ok = false;
    for(int i = 1; i <= n; i++) {
        if(str[i]) {
        if(ok) cout << " ";
        cout << i;
        ok =true;
        }
    }
    cout << endl;
    cout << y << endl;
    ok = false;
    for(int i = 1; i <= n; i++) {
        if(!str[i]) {
            if(ok) cout << " ";
            cout << i;
            ok = true;
        }
    }
    cout << endl;
    return 0;
}

D题(coderforces154B)
至今未过过一阵子再来吧=-=

SCU集训队第三次周赛记录

标签:

原文地址:http://blog.csdn.net/jibancanyang/article/details/45276611

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!