寒假训练赛第五场

问题 A: 分火腿

题目描述

小月⾔要过四岁⽣日了,她的妈妈为她准备了n根⽕腿,她想将这些⽕腿均分给m位小朋友,所以她可能需要切⽕腿。为了省事,小月⾔想切最少的⼑数,使这n根⽕腿分成均等的m份。请问最少要切⼏⼑?

输入

第⼀⾏⼀个整数T,表示有T组数据。
接下来T组数据,每组共⼀⾏,有两个数字n,m。

输出

每组数据⼀⾏,输出最少要切的⼑数。

样例输入 Copy

2
2 6
6 2

样例输出 Copy

4
0

思路
一开始题目没说2根香肠分3份只要切2刀,wa了,后来考虑了这种情况,找规律可得解;

ll gcd(ll a,ll b)
{
    if(b==0) return a;
    else return gcd(b,a%b);
}

int main()
{
    int n;cin>>n;
    while(n--)
    {
        ll x,y;
        cin>>x>>y;
        if(y==0||x%y==0) cout<<0<<endl;
        else if(y%x==0)
        {
            ll z=y/gcd(x,y);
            cout<<(z-1)*x<<endl;
        }
        else
            cout<<y-gcd(x,y)<<endl;
    }
    return 0;
}

问题 B: 工资

题目描述

n+e在暑假参加了打零⼯的活动,这个活动分为n个⼯作日,每个⼯作日的⼯资为Vi。有m个结算⼯钱的时间,n+e可以自由安排这些时间,也就是说什么时候拿钱,老板说的不算,n+e才有发⾔权!(因为n+e是⼟豪,他是老板的老板)
n+e不喜欢身上⼀次性有太多的钱,于是他想安排⼀下拿钱的时间,使他⼀次性拿的钱中最⼤的那次的最小。(最后⼀天⼀定要领钱)

输入

第⼀⾏2个数n,m
接下来n⾏,每⾏⼀个数,代表Vi

输出

输出⼀⾏⼀个整数,表示最小的最⼤钱数。

样例输入 Copy

7 5
100
400
300
100
500
101
400

样例输出 Copy

500

提示

100 400//300 100//500//101//400// ”//” 表示 n+e 要去拿钱。

对于20%的数据,1<=n<=20
对于另20%的数据,1≤n≤50,Vi的和不超过1000
对于100%的数据,1≤n≤100000,m≤n,Vi≤100000

思路
二分答案ans,判断mid是否符合judge函数的判断,符合判断则满足分组要求,可以将 r 减小,否则将 l 增大。

int n,m;
ll a[100005];///用long long

bool judge(ll mid)
{
    int cnt=0;
    ll ret=0;
    for(int i=1;i<=n;i++)
    {
        if(ret+a[i]>mid)
        {
            ret=a[i];
            cnt++;
        }
        else ret+=a[i];
        if(cnt>=m || ret>mid)///有多于m个分组是大于mid的,则非法
            return false;    ///或者是其中一个数ret大于mid,也非法
    }
    if(cnt<m) return true;
    return false;
}

int main()
{
    cin>>n>>m;
    ll ans,minn=1000000,maxn=0;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
        maxn+=a[i];
        minn=min(minn,a[i]);
    }
    while(minn<maxn)
    {
        ll mid=(minn+maxn)/2;
        if(judge(mid)) maxn=mid;
        else minn=mid+1;

    }
    cout<<minn<<endl;
}

问题 C: 公约数

题目描述

话说CD比较⽋扁,他表示在课室的日⼦没有教主在旁边打他的日⼦太寂寞了,所以这⼀晚,他终于来到了电脑室被打。由于CD是⼤家的宠物,于是⼤家都来打CD了。
电脑室里有n个⼈,第i个⼈希望打CD ai下。但是太多⼈打CD,他又会不爽,于是他规定只能有K个⼈打到他,并且为了公平起见,最终K个⼈打他的次数都必须是相同的,CD规定这个次数就是这K个⼈希望打他的次数的最⼤公约数。为什么是最⼤公约数呢?因为他觉得被打的次数是GCD的话他才会变成Glad CD。
之前说了,CD比较⽋扁,于是CD希望,K个⼈打他的次数的和最⼤。你能告诉他他最后总共会被打多少下么?

输入

第⼀⾏两个正整数n,k。
第⼆⾏n个正整数,表示每个⼈希望打CD多少下。

输出

输出⼀个正整数表示CD会被打多少下。

样例输入 Copy

3 1
1 2 3

样例输出 Copy

3

提示

对于30%的数据,保证k≤n≤20。
对于50%的数据,保证输⼊中所有数小于5000。
对于100%的数据,保证输⼊中所有数小于500000,k≤n。

思路:暴力枚举: i 从a[i]_max开始枚举到1,查询是否有大于等于k个数数是i的倍数,若有,则i是最大公约数。

int n;
ll k;
int visit[500005];
int main()
{
    cin>>n>>k;
    int maxn=0;
    for(int i=1;i<=n;i++)
    {
        int x;
        scanf("%d",&x);visit[x]++;
        maxn=max(maxn,x);
    }
    for(int i=maxn;i>=1;i--)
    {
        int cnt=0;
        for(int j=i;j<=maxn;j+=i)///查询是否存在i的倍数
        {
            if(visit[j])cnt+=visit[j];///存在,则计算有多少个
            if(cnt>=k) break;
        }
        if(cnt>=k)
        {
            printf("%lld",i*k);///cout会出错
            break;
        }
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章