Round 1C 2022 - Code Jam 2022 B.Squary(数学、思维)

题目

T(T<=100)组样例,每次给定n(n<=1000)个数,第i个数ei(-1000<=ei<=1000),

你需要添加最多k个[-1e18,1e18]范围内的整数,

使得这n+k个数的平方和与和的平方相等,即\sum_{i=1}^{n+k}a_{i}^{2}=(\sum_{i=1}^{n+k}a_{i})^{2}

如果无论如何也不能相等,输出IMPOSSIBLE

小范围:k=1

大范围:k<=1000

思路来源

官方题解

题解

考虑k=1的时候怎么做,设要添加的数为x,移项解出x的值,

x=\frac{\sum_{i=1}^{n}a_{i}^2-(\sum_{i=1}^{n}a_{i})^2}{2*(\sum_{i=1}^{n}a_{i})^2}

即不妨称sum为n个数的和,sum_{2}为n个数的平方和, 

x=\frac{sum_{2}-sum*sum}{2*sum}

在k>1时,分母2*sum启发我们,不妨尝试令新的和sum'为1,

则需要先补一个1-sum的值,

对应的新的平方和sum_{2}'=sum_{2}+(1-sum)*(1-sum)

即有x=\frac{sum_{2}'-1}{2}

注意到sum'=1为奇数,说明当前n+1个数中有奇数个奇数,

则其平方和也必为奇数,即sum_{2}'-1必为偶数,x=\frac{sum_{2}'-1}{2}必为整数

这表明,k>1时一定有解,且补上两个数1-sumx即可

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e3+10;
int t,n,k;
ll a[N];
int main(){
    scanf("%d",&t);
    for(int ca=1;ca<=t;++ca){
        scanf("%d%d",&n,&k);
        ll sum=0,sum2=0,ans;
        printf("Case #%d: ",ca);
        for(int i=1;i<=n;++i){
            scanf("%lld",&a[i]);
            sum+=a[i];sum2+=a[i]*a[i];
        }
        if(k>=2){
            sum2+=1ll*(1-sum)*(1-sum);
            printf("%lld ",1-sum);
            sum=1;
        }
        if(!sum){
            if(sum*sum==sum2){
                puts("0");
            }
            else{
                puts("IMPOSSIBLE");
            }
            continue;
        }
        if((sum2-sum*sum)%(2ll*sum)){
            puts("IMPOSSIBLE");
        }
        else{
            ans=(sum2-sum*sum)/(2ll*sum);
            printf("%lld\n",ans);
        }
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Code92007

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值