Codeforces Round 951 (Div. 2) C. Earning on Bets (数学)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


首先题目的意思是你要给n个结果都分配硬币,这些结果中只有一个会获胜,并给你你分配的硬币乘以k的硬币。
并且你分配的硬币之和必须要小于你赢得的硬币,注意这里赢得的硬币你必须要满足n种获胜的情况。

那么根据题干就可以得到最直接的一个式子,假如我们把我们分配出去的硬币的和设为 S u m Sum Sum,每个情况分配的硬币设为 a i a_i ai
那么就可以得到: S u m < k i ∗ a i Sum < k_i*a_i Sum<kiai
就可以推得: s u m k i < a i \frac{sum}{k_i} < a_i kisum<ai
所以我们每个硬币分配的数量都应该大于 s u m k i \frac{sum}{k_i} kisum
所以我们必须满足 ∑ i = 1 n s u m k i < s u m \sum_{i = 1}^{n}\frac{sum}{k_i} < sum i=1nkisum<sum
左右同除 s u m sum sum得到: ∑ i = 1 n 1 k i < 1 \sum_{i = 1}^{n}\frac{1}{k_i} < 1 i=1nki1<1
这就是最终的式子了,但是题目要求分配的是正整数,不能分配分数个硬币,所以我们直接求出所有 k i k_i ki的公倍数,让这些分数全部化为整数。

最后只需要验证一下,如果: ∑ i = 1 n 1 k i l c m ( k 1 , k 2 , … k n ) < l c m ( k 1 , k 2 , … k n ) \sum_{i = 1}^{n}\frac{1}{k_i}lcm(k_1,k_2,\dots k_n) < lcm(k_1,k_2,\dots k_n) i=1nki1lcm(k1,k2,kn)<lcm(k1,k2,kn)
那么就说明这种分配方式是存在的可行的。

#include<bits/stdc++.h>
using namespace std;
#define int long long
int gcd(int a,int b){
    return b ? gcd(b,a%b) : a;
}

int lcm(int a,int b){
    return a*b/gcd(a,b);
}

void solve(){
    int n;cin >> n;
    vector<int>k(n+1);
    int now = 1;
    for(int i = 1;i <= n;i++){
        cin >> k[i];
        now = lcm(now,k[i]);
    }

    vector<int>ans(n+1);
    int sum = 0;
    for(int i = 1;i <= n;i++){
        ans[i] = now/k[i];
        sum += ans[i]; 
    }

    if(sum < now){
        for(int i = 1;i <= n;i++)cout << ans[i] << ' ';
        cout << endl;
    }else{
        cout << -1 << endl;
    }
}

int main(){
    int T;cin >> T;
    while(T--){
        solve();
    }
    return 0;
}
  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值