CF1656D K-good Solution

题目传送门

做法

奇偶性判定好题。

Case1: n 为奇数

很显然,n 为奇数时一定可以拆分成两个数 xy,且 x 为奇数,y 为偶数,发现 xmod2=1,ymod2=0k 也刚好位 2,所以当 n 为奇数时就直接输出 2

Case2: n 为偶数

k 个数为 a1,a2,...,ak,所以有 a1+a2+..+ak=n,由于题目说 a1modk,a2modk,...,akmodk 互不相同,所以这些数 modk 一定为 0,1,2,...,k1 且不重不漏。

那么考虑拆分 ai,设 ai=bi×k+ci(ci=aimodk),那么 a1+a2+...+ak=n 就可以转化为 (b1×k+b2×k+...+bk×k)+(c1+c2+...+ck)

因为 c1+c2+...+ck 一定等于 0+1+...+k1,等差数列求和得 (0+k1)×k2=(k1)×k2,再把 b1×k+b2×k+...+bk×k 提取公因式得 k×(b1+b2+...+bk),再设 b1+b2+...+bk=x,所以 b1×k+b2×k+...+bk×k=k×x

所以 n=(k1)×k2+k×x,将上式化简得 2×n=k×(k+2×x1),然后我们发现一个结论:kk+2×x1 中一定有一个为偶数,一个为奇数,因为 2×x1 一定为奇数,所以如果 k 为偶数,那么 k+2×x1 就一定为奇数,上述结论肯定成立,如果 k 为奇数,那么 k+2×x1 一定为偶数, 故得证。

所以我们把 2×n 拆成 2p+q,使得 2p|2×nq,而 2p+12×nqq<2p,那么这样做显然 q 为奇数,这样拆是把这个数拆成偶数乘奇数的形式。

a=2p,b=q那么可以证明 k 一定可以等于 min(a,b),如果这样拆后 min(a,b)1 就说明无解(因为题目中说的是 2k,与题目矛盾),输出 1,否则就输出 ab 中较小的一个(为什么要输出较小的一个?是因为 k2×x1+k,两个数 ab 就相当于 k2×x1+k,所以较小的一个就为 k)。

代码

#include<bits/stdc++.h>
using namespace std;
int T;
long long n;
int main()
{
    scanf("%d",&T);
    while(T--)
    {
        scanf("%lld",&n);
        if(n%2==1)//n为奇数时直接特判
        {
            printf("2\n");
            continue;
        }
        else//n为偶数
        {
            long long a=1,b=0,x=2*n;
            while(x%2==0)
            {
                x/=2;a*=2;//将2*n这个数拆分成奇数乘偶数的形式
            }
            b=(2*n)/a;
            if(min(a,b)<2)printf("-1\n");//a、b的最小值小于2,无解
            else if(a<b)printf("%lld\n",a);//输出较小的一个数
            else if(a>b)printf("%lld\n",b);
        }
    }
    return 0;
}
posted @   wangyuanbo  阅读(7)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统
· 【译】Visual Studio 中新的强大生产力特性
· 2025年我用 Compose 写了一个 Todo App
点击右上角即可分享
微信分享提示