SCU集训队第三次周赛记录

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)

至今未过过一阵子再来吧=-=

时间: 2024-08-05 11:13:04

SCU集训队第三次周赛记录的相关文章

SCU集训队第四次周赛

A题(hdu2600 war): 用数组记录标记即可,开始不知道是多组数据以为是Coderforces的题数wa,以后周赛还是都写成多数据吧也好调试,然而多数据就要多注意初始化了.罗大神一直挂在名字可能有多个单词. 我这种开数组模拟的方法如果数据再大点就会ML,最好把开始和结尾存到一个结构体数组中,以终点为标准来结构体排序(如果终点相同起点小的靠前),然后从数组的最右边开始扫,如果第一个数都终点小于边界直接数组b,否则输出扫到的第一个,起点大于上一个终点的情况,扫完了都没有就输出Badly!.

《C++11/14高级编程Boost程序库探秘》之第1章全新的C++语言(三)学习记录

<C++11/14高级编程Boost程序库探秘>之第1章全新的C++语言(三)学习记录 1.7函数式编程 函数式编程是与面向过程编程.面向对象编程和泛型编程并列的一种编程范式,它基于λ演算理论,把计算过程视为数学函数的组合运算. 1.7.1 lambda表达式 基本形式为: [](params){...} []称为lambda表达式引出操作符,圆括号里是函数的参数,花括号内则是函数体,可以使用任何C++语句. lambda表达式的类型称为闭包,无法直接写出,所以通常需要使用auto的类型推导功

建立空窗口时,窗口函数受到的消息(三种拦截记录消息的方法)

新窗体上放一个Button1和Panel1,仅仅Form1就会收到以下消息: procedure TWinControl.DefaultHandler(var Message); begin if FHandle <> 0 then begin with TMessage(Message) do begin if (Msg = WM_CONTEXTMENU) and (Parent <> nil) then begin Result := Parent.Perform(Msg, W

Android Studio第三十一期 - 记录RecyclerView滚动位置并恢复

代码已经整理好,看下面~有一天你会用到的~不客气哈~ //监听RecyclerView滚动状态 mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {     @Override     public void onScrollStateChanged(RecyclerView recyclerView, int newState) {         super.onScrollStateChanged(r

第三次周赛题解【并查集 KMP DFS BFS 快速幂】

问题 A: 一道签到题 时间限制: 2 Sec  内存限制: 128 MB 提交: 63  解决: 28 [提交][状态][讨论版] 题目描述 我想说这是一道签到题,意思就是本次测试中最水的一道,不过我这样说你真的愿意相信我吗?哈哈,题目是这样的给你一下小数,然后请告诉我分别告诉我这个小数的循环节的循环次数.循环节以及循环节长度 输入 输入包括多组测试数据每组测试数据1行,包括一个小数,小数的长度不超过200,小数大于0小于100 输出 分别输出这个小数的循环节的长度.循环节以及循环次数,中间以

(三)maven出错记录

此处因为是自己做的所以文笔带过,简单描述下 1\首先是jsp页面报错,缺少必要的servletx依赖jar包,需要在pom中配置 <dependency><groupId>javax.servlet</groupId><artifactId>servlet-api</artifactId><version>2.5</version><scope>compile</scope></depende

Linux IPC 同步(三):记录锁

进程间的互斥,我们可以让这些进程共享某个内存区(mmap实现),然后在该共享内存区中使用某种类型的同步变量 但是,fcntl记录上锁往往更容易使用. #include <unistd.h> #include <fcntl.h> int fcntl(int fd, int cmd, ... /* struct flock *arg */ ); struct flock { ... short l_type; /* Type of lock: F_RDLCK, F_WRLCK, F_U

武汉三首,记录备忘,写的不好,以后再改

第一首:拜望武昌英烈间再登黄鹤谒先贤隐水洞中寻幽境泛舟东湖妙如仙 第二首悲凉:追随圣迹到武昌千年之后望长江摩肩接踵登黄鹤但见高楼列两厢滚滚长江依旧逝唯看神桥锁大江纵使李杜今犹在已无风景写新章 第三首喜悦: 追随圣迹到武昌千年之后望长江滚滚长江依旧逝但见长桥锁大江 自古英雄皆俯首天堑早已变通畅若那李杜今犹在定为盛世写新章 原文地址:https://www.cnblogs.com/liuzhendong/p/10301616.html

第三次周赛D题

题意: 多次询问树上两点最短 距离. TLE做法:对每次询问跑一遍最短路,用堆优化迪杰斯特拉的话复杂度大概为\(O(q*(n+m)logm)\). \(100\)分做法: 用一个\(dis\)数组记录根节点\(root\)到每一个节点的距离,那么树上两点\(u,v\)的距离就是\(root\)到\(u\)的距离加上\(root\)到\(v\)的距离减去两倍的\(root\)到\(lca(u,v)\)的距离(可以画下图感性理解...),即 \(ans=dis[u]+dis[v]-2*dis[lca