题解 CF1864C Divisor Chain

题意

给定一个整数 x (2x109),你每次可以选择一个 dx,并将 x=xd

你需要做这样的操作至多 1000 次,并且不能使用同一个 d 超过 2 次。

求解将 x 变为 1 的操作序列。

分析

赛时找了很久规律,才发现是二进制拆分。

x 进行二进制拆分,设 x=i=1m2bi, 满足 i[1,m),bi>bi+10

观察可以发现:a1=x=i=1m2bi=2bmi=1m2bibm2bma1a2=a12bm=i=1m12bi=2bm1i=1m12bibm12bm1a22b1am 所以可以证明:i[1,m],2bmi+1ai 所以我们可以从小到大依次减去 2 的最低次幂,直到仅剩 2 的最高次幂。

接着将 2 的最高次幂依次砍半即可,易证每个减数不会使用超过 2 次。

代码

//the code is from chenjh
#include<cstdio>
#include<algorithm>
#include<vector>
void solve(){
    int x;scanf("%d",&x);
    std::vector<int> v;//操作序列。
    v.emplace_back(x);
    int y=1<<std::__lg(x);//求 x 的 2 的最高次幂。
    int z=x-y;
    for(int i=0;i<=30;i++)if(z&(1<<i))v.emplace_back(x-=(1<<i));//从小到大减去这一位。
    while(y>1)v.emplace_back(y>>=1);//每次砍半。
    printf("%zu\n",v.size());
    for(const int y:v) printf("%d ",y);
    putchar('\n');
}
int main(){
    int T;scanf("%d",&T);
    while(T--) solve(); 
    return 0;
}
posted @   Chen_Jinhui  阅读(38)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】

一言

温柔解救不了这个世界
——罪恶王冠
点击右上角即可分享
微信分享提示