Codeforces Round 924 (Div. 2) --- E. Modular Sequence ---- 题解

E. Modular Sequence:

题目描述:

思路解析:

这里第一个一定要需要填充x,然后后面每一位填充 ai-1 + y 或者 ai-1 % y,那么其实相当于除了第一位固定,后面每一位都可以表现为 a + ki * y;其中 a = x % y。这是显然的。那么ki有一个性质,ki 要么等于 ki-1 + 1 要么为 0.

那么问题就转化成 ki的和 等于 (s - x - (n-1) * a) / y; 

那么我们只需要找到满足这样至少需要满足这样的和至少需要多少位,如果少于n-1位即可。(这个需要多少位,可以通过预处理得到)如果我们让第二位接在第一位,那这样预处理是没意义的,他只能针对这一种情况,所以我们让第二位k2为0,但是这样可能导致无法满足,那在这种情况下,我们让第二位接在第一位上,然后让k3为0,如果不行,继续往后延。

这样如果存在满足条件我们一定能得到。

代码实现:

import java.util.*;


import java.io.*;

public class Main {
    static int[] a;
    static int[] dp;
    static int[] from;
    public static void main(String[] args) throws IOException {
        a = new int[633];
        a[1] = 0;
        for (int i = 2; i < 633; i++) {
            a[i] = a[i-1] + i-1;
        }
        dp = new int[200005];
        Arrays.fill(dp, Integer.MAX_VALUE / 10);
        dp[0] = 0;
        from = new int[200005];
        for (int i = 1; i <= 200000; i++) {
            for (int j = 2; j <= 632; j++) {
                if (i - a[j] < 0) break;
                if (dp[i] > dp[i-a[j]] + j){
                    dp[i] = dp[i-a[j]] + j;
                    from[i] = i-a[j];
                }
            }
        }
        int t = f.nextInt();
        while (t > 0) {
            solve();
            t--;
        }
        w.flush();
        w.close();
    }

    public static void solve() throws IOException{

        int n = f.nextInt();
        int x = f.nextInt(); int y = f.nextInt(); int ned = f.nextInt();
        int a = x % y;
        if ((ned - x - (n - 1) * a) % y != 0 || (ned - x - (n-1) * a) < 0) {
            w.println("NO");
            return;
        }
        if (n == 1 ){
            if (ned == x) {
                w.println("YES");
                w.println(ned);
            }else {
                w.println("NO");
            }
            return;
        }
        int[] res = new int[n+1];
        res[1] = x;
        ned -= x;
        x+=y;
        for(int s = 2; s <= n; s++){
            if (ned < 0) break;
            int c = (ned - (n-s+1) * a) / y;
            if (c < 0) break;
            int d = c ;
            if (dp[c] <= n-s+1){
                w.println("YES");
                for (int i = 1; i < s; i++) {
                    w.print(res[i] + " ");
                }
                while (c != 0){
                    int r = dp[c];
                    int l = dp[from[c]];
                    c = from[c];
                    for (int i = l+1; i <= r; i++) {
                        w.print((i - l - 1) * y + a + " ");
                    }
                }
                for (int i = dp[d] + 1; i <= n-s+1; i++) {
                    w.print(a + " ");
                }
                w.println();
                return;
            }
            res[s] = x;
            ned -= x;
            x+=y;
            if (s == n && ned == 0){
                w.println("YES");
                for (int i = 1; i <= n; i++) {
                    w.print(res[i] + " ");
                }
                w.println();
                return;
            }
        }
        w.println("NO");

    }





    static PrintWriter w = new PrintWriter(new OutputStreamWriter(System.out));
    static Input f = new Input(System.in);

    static class Input {
        public BufferedReader reader;
        public StringTokenizer tokenizer;

        public Input(InputStream stream) {
            reader = new BufferedReader(new InputStreamReader(stream), 32768);
            tokenizer = null;
        }

        public String next() throws IOException{
            while (tokenizer == null || !tokenizer.hasMoreTokens()) {
                tokenizer = new StringTokenizer(reader.readLine());
            }
            return tokenizer.nextToken();
        }

        public int nextInt() throws IOException {
            return Integer.parseInt(next());
        }

        public long nextLong() throws IOException {
            return Long.parseLong(next());
        }

        public Double nextDouble() throws IOException {
            return Double.parseDouble(next());
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Studying~

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

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

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

打赏作者

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

抵扣说明:

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

余额充值