首页 > 试题广场 >

密码生成

[编程题]密码生成
  • 热度指数:6529 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解
小汪作为一个有数学天分的程序猿,设计了一套密码生成器来搞定自己的密码问题。
密码生成器由 N 个槽位组成,槽位的下标为 0~N-1 ,每个槽位存储一个数。起初每个槽位都是 0 。
密码生成器会进行 M 轮计算,每轮计算,小汪会输入两个数 L , R (L<=R),密码生成器会将这两个数作为下标,将两个下标之间(包含)的所有槽位赋值为 i( i 为当前的轮次, i ∈ [1,M])。
M轮计算完成后,密码生成器会根据槽位的最终值生成一条密码,密码的生成规则为:
(0*a[0] + 1*a[1] + 2*a[2] + ... + (N-1)*a[N-1]) mod 100000009
其中a[i]表示第i个槽位的最终值。
请帮助小汪把他的密码生成器实现为代码。

数据范围:
对于前30%的测试数据,保证 N,M<=10000
对于前50%的测试数据,保证 N,M<=200000
对于100%的测试数据,保证 N<=1.5*10^7,M<=200000

输入描述:
第一行为两个整数N,M,表示槽位个数和计算轮数。
接下来M行,每行两个整数Li,Ri,表示第i轮计算的输入。


输出描述:
输出一行,一个整数A,表示小汪的开机密码。
示例1

输入

5 3
2 3
1 2
1 1

输出

10

说明

对于输入样例,密码生成过程如下:

初始: 0 0 0 0 0
第1轮:0 0 1 1 0
第2轮:0 2 2 1 0
第3轮:0 3 2 1 0
密码生成器最终生成 0 3 2 1 0,则密码为(0*0 + 3*1 + 2*2 + 1*3 + 0*4) mod 100000009 = 10

备注:
mod 表示取余操作,a mod b表示a,b相除得到的余数
对于前30%的测试数据,保证 N,M<=10000
对于前50%的测试数据,保证 N,M<=200000
对于100%的测试数据,保证 N<=1.5*10^7,M<=200000
100分。非暴力。用差分的思想。
创建数组存操作记录,在区间左端记录+i,区间右端记录-i。
创建一个优先队列,从左往右遍历所有操作,遇到+就add(i),遇到-就remove(i)。
每个位置的密码就是这时优先队列大顶端的数。

(用PriorityQueue会超时,这里用布尔数组实现了同样的功能
import java.util.Scanner;

public class Main {

    static class Node {
        int i;
        boolean set;
        Node prev;

        public Node(int i, boolean set, Node prev) {
            this.i = i;
            this.set = set;
            this.prev = prev;
        }
    }

    static class PriorityQueue {
        private final boolean[] active;
        private int max;

        public PriorityQueue(int upperBound) {
            active = new boolean[upperBound + 1];
            active[0] = true;
            max = 0;
        }

        public void add(int i) {
            active[i] = true;
            if (i > max)
                max = i;
        }

        public void remove(int i) {
            active[i] = false;
            if (max == i)
                while (!active[max]) max--;
        }

        public int peek() {
            return max;
        }
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int m = sc.nextInt();
        Node[] nodes = new Node[n + 1];
        for (int i = 1; i <= m; i++) {
            int l = sc.nextInt();
            int r = sc.nextInt();
            nodes[l] = new Node(i, true, nodes[l]);
            nodes[r + 1] = new Node(i, false, nodes[r + 1]);
        }
        long res = 0;
        PriorityQueue pq = new PriorityQueue(m);
        for (int index = 0; index < n; index++) {
            Node node = nodes[index];
            while (node != null) {
                if (node.set) {
                    pq.add(node.i);
                } else {
                    pq.remove(node.i);
                }
                node = node.prev;
            }
            int a_i = pq.peek();
            res = (res + (long) index * a_i) % 100000009L;
        }
        System.out.println(res);
    }
}
编辑于 2021-09-09 20:55:21 回复(2)
import java.util.Scanner;
public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n=sc.nextInt();
        int m=sc.nextInt();
        int[] a=new int[n];

        for (int i = 0; i < m; i++) {
            int L=sc.nextInt();
            int R=sc.nextInt();
            a[L]=i+1;
            if (R!=L) {
                a[R] = i + 1;
            }
        }
        int sum=0;
        for (int i = 1; i < a.length; i++) {
            sum=sum+i*a[i];
        }
        int anw=sum%100000009;
        System.out.println(anw);
    }
}


虽然方法有点傻,但是感觉应该没什么问题啊,为什么通不过呢?求大佬解惑
编辑于 2020-07-09 15:37:32 回复(4)