Codeforces Round #561 (Div. 2) D. Cute Sequences(数学+贪心)

题目链接
题目大意:在这里插入图片描述
思路:构造一个这样的序列。
特判一下答案长度在1,2的情况。
我们假设有解,且长度为 k k ,那么显然我们可以得到一个等式:
1.设 b b 数组为每次加的值, b 1 = 0 b_1=0
2. i = 1 k 1 2 k i 1 b i + b n + A 2 k 2 = B \sum_{i=1}^{k-1}2^{k-i-1}*b_i+b_n+A*2^{k-2}=B
因为 b i [ 1 , m ] b_i\in[1,m] ,所以初始的 b b 全为 1 1 ,最多加到 m m ,那么我们枚举长度 k k
每次先判断合不合法:即 b b 全是1的和是不是比 B B 小,显然比 B B 才有可能合法。
然后每次去把多余的部分从大到小 (幂次高到低)开始减 ,每次尽量减的最多。
如果最后剩下的在 [ 1 , m ] [1,m] 之间即合法,把这部分赋值给 b [ k ] b[k] 即可。
细节见代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=2e5+10;
#define fi first
#define se second
#define pb push_back
int t;
LL a,b,m,ans[N],sum[N],f[N],add[N];
LL g[55][55];
LL vis[55],re[55];
int main() {
    ios::sync_with_stdio(false);
    f[0]=1;
    for(int i=1;i<=50;i++)f[i]=f[i-1]*2;
    for(int i=2;i<=50;i++){
        for(int j=i-1;j>=1;j--){
            g[i][j]=f[i-j-1];
        }
        g[i][i]=f[0];
    }
    for(cin>>t;t;t--){
        cin>>a>>b>>m;
        if(a==b){
            cout<<"1\n"<<a<<'\n';
        }else if(b-a<=m){
            cout<<2<<'\n';
            cout<<a<<' '<<b<<'\n';
        }else{
            int sta=0;
            for(int i=3;i<=50;i++){
                LL res=0;
                int st=0;
                memset(vis,0,sizeof vis);
                memset(re,0,sizeof re);
                if(g[i][1]*a>b)break;//不合法
                res=b-g[i][1]*a;
                LL need=(1ll<<(i-2))-1;
                if(need+1>res)continue;//判断是否可能合法,最后一个至少要留1
                for(int j=0;j<=i-3;j++)ans[j]=1;
                res-=need+1;
                int ma=i-3;
                while(ma>=0&&res>1){
                    LL ud=max(min((res)/(1ll<<ma),m-1),0ll);//不停的减
                    res-=ud*(1ll<<ma);
                    ans[ma]+=ud;
                    ma--;
                }
                res++;//把之前保留的1加上
                if(res<1||res>m)st=1;
                if(!st){
                    add[i]=res;
                    add[i-1]=ans[0];
                    for(int j=i-2;j>=2;j--){
                        add[j]=ans[i-j-1];
                    }
                    sum[1]=a;
                    ans[1]=a;
                    for(int j=2;j<=i;j++){
                        ans[j]=sum[j-1]+add[j];
                        sum[j]=ans[j]+sum[j-1];
                    }
                    cout<<i<<' ';
                    for(int j=1;j<=i;j++)cout<<ans[j]<<' ';
                    cout<<'\n';
                    sta=1;
                    break;
                }
            }
            if(!sta)cout<<-1<<'\n';
        }
    }
    return 0;
}
发布了160 篇原创文章 · 获赞 81 · 访问量 9663

猜你喜欢

转载自blog.csdn.net/qq_40655981/article/details/103734636