• 浙江理工大学7月月赛


     比赛网址  http://47.96.116.66/contest.php?cid=1376

    A题分组

    题目描述

    小明的班级在上体育课,老师想让大家分成两组玩拔河。现在大家排成了一排,老师嫌麻烦,所以想直接在队伍中间找个位置断开,这样不就分成了两组了吗?但是这个老师的思维很奇怪,他觉得分成人数相等的两组会不公平,他想让两组的体重和的差最小(差值要求体重和大的值减小的值)。老师把这个任务交给了小明,你能帮帮他吗?

    输入

    第一行为一个正整数n,表示小明班的人数。 
    第二行为n个正整数,表示这一排从左到右同学的体重。

    输出

    只有一行,为题目描述中最小的差值。

    样例输入

    5
    11 17 3 2 20

    样例输出

    3

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<cstdlib>
    #include<map>
    #include<vector>
    const int N=1e5+5;
    int sum1,sum2,a[N];
    int n,i,j;
    using namespace std; 
    int main()
    {
        int ans=0x3f3f3f;
        sum1=0;
        sum2=0;
        scanf("%d",&n);
        for(i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            sum1+=a[i];
        }
        for(i=1;i<=n;i++)
        {
            sum2+=a[i];
            ans=min(ans,abs(sum2-sum1+sum2));
        }
        printf("%d
    ",ans);
    }
    View Code
     

       B题:数学老师的难题

    题目描述

    学好数学是学好计算机的一个重要基础,毕竟早期计算机科学是数学科学的一个重要分支。帅帅也明白这个道理,因此,帅帅在学校既参加了数学兴趣班也参加了计算机兴趣班。但帅帅马上就要参加2010年东莞市小学程序设计竞赛了,因此就暂停了数学兴趣班的学习,数学老师知道后很生气,后果很严重,于是数学老师就给帅帅出了一个难题:统计两个正整数t1 、 t2 ( t1 不一定大于 t2 ) 之间的所有数的约数个数和S,这本是一个很简单的题目,但数学老师为了难倒帅帅,给出的两个数t1、t2的非常大,为10000000以内的正整数。 
    但帅帅的编程能力还处于入门阶段,希望你能帮他解决这个问题?

    输入

    输入文件problem.in仅包含一行,共有两个整数,表示t1 t2 (用空格分开)

    输出

    输出文件仅有一个整数,表示t1 , t2之间的约数个数之和

    样例输入

    2 6

    样例输出

    13

    提示

    2的约数有1,2共2个;
    3的约数有1,3共2个; 
    4的约数有1,2,4,共3个; 
    5的约数有1,5共2个;
    6的约数有1,2,3,6,;共4个。
    所以2到6的约数个数为13
    【数据规模】

    对于50%的数据保证有t1,t2<=5000000 
    对于全部的数据保证有t1,t2<=10000000
     
    约数即因数,例如4的约数有1,2,4。如果是要求出一个数具体的约数,只能用for/while循环,复杂度不会超过O(n),但是本题还要求出区间内数的约数和,数与数之间的关系也不是很紧密,无法简化运算,很可能会超时。但若是改为仅求约数的个数,就可以另辟蹊径。设一个区间[1,N],显然,这些数的因数都含有1,即因数1的个数有N/1个。而含有因数为2的数有2,4,6...2*k...,即因数2的个数有N/2,依此类推,因数3的个数有N/3...因数K的个数有N/K,所以,重点来了!区间[1,N]的所有因数之和是多少?没错,就是$sum_{i=1}^{N}frac{N}{i}$ ;我们知道了1到N的因数之和,怎么求N到M的因数之和呢?想必已十分简单.
    代码
     
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<cstdlib>
    #include<map>
    #include<vector>
    long long n,m,i,j;
    long long sum2,sum1;
    using namespace std; 
    int main()
    {
        sum1=0;
        sum2=0;
        scanf("%lld%lld",&n,&m);
        long long maxx,minn;
        minn=min(n,m);
        maxx=max(n,m);
        n=minn;
        m=maxx;
        for(i=1;i<n;i++)
        {
            sum1+=(n-1)/i;
        }
        for(i=1;i<=m;i++)
        {
            sum2+=m/i;
        }
        //printf("%d
    ",sum1);
        //printf("%d
    ",sum2);
        printf("%lld
    ",sum2-sum1);
    }
    View Code

    问题 C: 一脸严肃的声明: 作业作假的行为是可耻的行为!

    题目描述

    一脸严肃的声明: 作业作假的行为是可耻的行为!
    有F个好朋友正在做物理作业,每个朋友要做M个实验,他们的实验数据会保存在data数组里面 前M个数据是第一个人的,接下来M个数据是第二个人的,以此类推
    一个序列的中位数是这个序列排序之后位于中间的那个数,如果序列的长度是偶数,中间两个数中较小的那个数就是中位数 {10,40,30,20}的中位数是20
    根据实验手册的答案,实验数据的结果应该是goal,他们想要改变一些实验数据使得data数组的中位数为goal 
    返回以下两个数  
    1: 最少需要多少个人进行数据造假  
    2: 在最少人作假的前提下,最少需要改变多少个实验数据 

    输入

    第一行输入三个正整数F,M,goal, 1 <= FM <=1000, 0 <= goal <= 99 接下来一行输入FM个数表示data数组, 每个元素的范围0 <= data[i] <= 99

    输出

     输出一行包含两个整数

    样例输入

    【输入样例1】
    5 5 8
    1 2 3 4 5 10 9 8 7 6 25 24 23 22 21 18 16 17 19 20 11 13 12 14 15
    【输入样例2】
    4 3 12
    3 8 12  3 8 12 3 8 12  8 12 17

    样例输出

    【输出样例1】
    1 5
    【输出样例2】
    1 2

    提示

     有5个朋友,每个人有5个数据,一共是25个数据
    当前的中位数是13,为了使其降到8, 第四个人可以改动实验数据
    从{18,16,17,19,20} 到 {3,1,3,5,7}.
     
    思路:准备两个数组,一个用来存储每个人比理想分数高的部分,另一个是比理想分数低的部分,然后排序,最后哪个人倒霉(要造假的数据多)就先上他了
    0_o
    代码:
     
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<cstdio>
    #include<vector>
    #include<cmath>
    using namespace std;
    const int N=1e6+5;
    int data[N],up[N],down[N];
    int i,j,n,f,m,goal;
    int median;
    int needc;
    int ans,num;
    int main()
    {
        memset(down,0,sizeof down);
        memset(up,0,sizeof up);
        scanf("%d%d%d",&f,&m,&goal);
        for(i=1;i<=f*m;i++)
        {
            scanf("%d",&data[i]);
            if(data[i]<goal)
            {
                down[(i-1)/m]++;
            }
            else if(data[i]>goal)
            {
                up[(i-1)/m]++;
            }
        }
        sort(data+1,data+1+f*m);
        sort(up,up+f);
        sort(down,down+f);
        median=data[(1+f*m)/2];
        if(median==goal)
        printf("0 0
    ");
        else
        { 
            if(median>goal)
            {
                needc=(1+f*m)/2-(upper_bound(data+1,data+1+f*m,goal)-data-1);
            }
            else
            {
                needc=lower_bound(data+1,data+1+f*m,goal)-data-1-(1+f*m)/2+1;
            }
            //printf("%d
    ",median);
            //printf("%d
    ",needc);
            num=needc;
            ans=0;
            if(median>goal)
            {
                while(needc>0)
                {
                    needc-=up[f-1];
                    f--;
                    ans++;
                }
            }
            else if(goal>median)
            {
                while(needc>0)
                {
                    needc-=down[f-1];
                    f--;
                    ans++;
                }
            }
            printf("%d %d
    ",ans,num);
        }
    }
    View Code

    问题 D: 猫抓老鼠

    题目描述

     一个平面直角坐标系上,有一只猫站在原点(0,0), 
    对于除原点外的每一个(x,y)(|x| <= N , |y| <= N)的位置上都有一只老鼠

    假如猫选择了某个方向出击,那么它可以吃掉这个方向上的所有碰见的老鼠

    现在问你有多少个方向上恰好有C只老鼠

    输入

     输入两个整数N, C (1 <= N <= 5000000, 1 <= C <= N)

    输出

     输出一个整数

    样例输入

    【样例输入1】
    2 2
    【样例输入2】
    2 1
    【样例输入3】
    1234 3

    样例输出

    【样例输出1】
    8
    【样例输出2】
    8
    【样例输出3】
    180608

      思路:先得搞清楚,在某个方向上,能抓到C只老鼠(不包括原点),则每只老鼠横坐标的间隔范围是多少?考虑两个极值:1,恰好第C只老鼠的横坐标为N,则distance=N/C。2,恰好第C+1只老鼠的横坐标为N(无法取到),则distance=N/(C+1);所以distance∈[N/C,N/(C+1))。我们先随便确定一个K∈[N/C,N/(C+1)),则K可以作为第一只抓到的老鼠的横坐标,这只老鼠的纵坐标可能大于K吗?不能,否则第C只老鼠的纵坐标将会大于N,所以第一只老鼠的Y<=X,那么,X和Y能有除1以外的因数吗?也不能。例如:假设X和Y有公因数2,则(X/2,Y/2)这个点的老鼠肯定会在之前被抓,还有(3X/2,3Y/2)的老鼠...这意味着如果X和Y有公因数(不为1)的话,猫抓到的老鼠是大于C的,即所有Y值的可能为<X的与X互质的数的个数,即X的欧拉函数,最后考虑坐标系的对称性*8即可(还有X==Y的特殊情况,这种情况下猫在沿X轴和斜45°能抓到一样多的老鼠,故同样算作欧拉函数)。

     代码:

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    int n,m,M,C;
    const int N=5e6+5;
    long long oula[N];
    long long prime[N];
    long long vis[N];
    int a,b;
    void  init(long long x)
    {
        memset(vis,0,sizeof vis);
        long long num=0;
        for(long long i=2;i<x;i++)
        {
            if(!vis[i])
            {
                prime[num]=i;
                num++;
                oula[i]=i-1;
            }
            for(long long j=0;j<num&&i*prime[j]<x;j++)
            {
                vis[i*prime[j]]=1;
                if(i%prime[j]==0)
                {
                    oula[i*prime[j]]=prime[j]*oula[i];
                    break;
                }
                else
                {
                    oula[i*prime[j]]=oula[i]*(prime[j]-1);
                }
            }
        }
    }
    int main()
    {
        while(scanf("%d%d",&M,&C)!=EOF)
        {
            int t1=M/C; 
            int t2=M/(C+1)+1;
            long long sum=0;
            //printf("%d %d
    ",t1,t2+1);
            init(t1+1);
            oula[1]=1;
            for(int i=t2;i<=t1;i++)
            {
                sum+=oula[i];
            }
            printf("%lld
    ",sum*8);
        }
    }
    View Code

    问题 F: 夏令营

    题目描述

     有n位OI选手准备展开一些一对一的单挑比赛.n是个偶数,每位选手都有自己的主场

    517编程委员会决定给n位选手组织一次夏令营,规则如下
    1: 夏令营恰好有两轮比赛
    2: 每位选手在每轮比赛中恰好参加一次
    3: 每两位选手最多在比赛中相遇一次
    4: 每位选手都在主客场恰好打了一次比赛

    现在你作为517编程委员会的筹划人员,需要计算一下一共有多少种不同的比赛安排方案
    由于方案数可能比较大,输出方案数对1e9+7取模的值

    备注: 每一场比赛可以用一个有序对(A,B)表示 A表示主场选手,B表示客场选手
    每一轮比赛是一些比赛的无序集合
    整个夏令营的安排方案是两轮比赛的有序对

    输入

     输入一个正整数n, (4 <= n <= 500000)
    n 是个偶数

    输出

     输出一个整数

    样例输入

    【样例输入1】
    4
    【样例输入2】
    8

    样例输出

    【样例输出1】
    12
    【样例输出2】
    15120

    提示

     样例一解释:
    假设四位选手分别用A B C D表示,(A,B)表示A是主场,B是客场
    其中的三种方案如下
    第一轮比赛: (A,B), (C,D). 第二轮比赛: (B,C), (D,A).
    第一轮比赛: (A,B), (D,C). 第二轮比赛: (B,D), (C,A).
    第一轮比赛: (C,A), (B,D). 第二轮比赛: (A,B), (D,C).

    其中第二种方案和第三种方案可以通过交换轮次获得,但是他们算不同的方案
     
    好,现在开始一年一度的夏令营比赛,开始随机匹配选手,上路是N/2个坑,下路也是这样,现在先选择一半倒霉的人丢进上面的坑,方法数是$C_{N}^{N/2} extrm{}$,还有一半的人怎么办?自己选择个坑跳,方法数是$Lambda _{N/2}^{N/2}$ ,然后两个坑的人换一下坑,原来在坑里对峙的人不能再次对峙,得换个人,这相当于一个错排,所以N个人的总跳坑数为$C_{N}^{N/2} extrm{}$ × $Lambda _{N/2}^{N/2}$ × DP[N/2]。
     
    代码 :
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<cstdio>
    #include<vector>
    #include<cmath>
    using namespace std;
    const int mod=1e9+7;
    const int N=5e5+5;
    long long a[N];
    int n,i,j,m;
    void DP(int x)
    {
        for(i=3;i<=x;i++)
        {
            a[i]=(i-1)*(a[i-1]+a[i-2])%mod;
        }
        return ;
    }
    int main()
    {
        a[1]=0;
        a[2]=1;
        scanf("%d",&n);
        m=n/2;
        DP(m);
        long long ans=1;
        for(i=n/2+1;i<=n;i++)
        {
            ans=ans*i%mod;
        }
        ans=ans*a[m]%mod;
        printf("%lld
    ",ans);
    }
    View Code
     
  • 相关阅读:
    RocketMQ主从搭建
    Spring Cloud Sleuth
    Spring Cloud Eureka
    Nacos配置中心使用
    Nacos注册中心使用
    Nacos快速入门
    Nginx配置SSL
    并发工具类
    关于类的线程安全
    Docker 入门学习笔记(一)
  • 原文地址:https://www.cnblogs.com/switch-waht/p/11166424.html
Copyright © 2020-2023  润新知