阅读(Read)

没有原题

似乎来自某校模拟赛….

Description

热爱看书的你有N本书, 第i本书的种类为A[i]. 你希望每天能够看一本书, 但是不希望连续两天看种类相同的书. 为了达成这个条件, 你需要选择一些书不看, 作为一个好学生, 你希望不看的书尽可能少, 求最少可以有多少书不看.

Input

为了避免输入文件过大, 我们采取如下方式生成A[i].
第一行读入两个个整数M, K.
接下来一行读入M个整数count[i], 其中N=∑count [i].
接下来一行读入M个整数X[i].
接下来一行读入M个整数Y[i].
接下来一行读入M个整数Z[i].
然后按照下面这段代码生成.

int N = 0, S = (1 << K) - 1;
for (int i = 1; i <= M; ++i) {
    N = N + 1;
    A[N] = X[i];
    long long last = X[i];
    for (int j = 1; j < count[i]; ++j) {
        last = (last * Y[i] + Z[i]) & S;
        N = N + 1;
        A[N] = last;
    }
}

注意:因为生成A[i]的方法不好用语言描述, 所以用代码来表达. 直接照搬代码的话后果自负.

Output

输出一个整数表示答案.

Sample Input

4 2
1 1 1 1
1 1 1 2
0 0 0 0
0 0 0 0

Sample Output

1

Hint

对于所有数据, N <= 50000000, M <= 1000, K <= 30, X[i], Y[i] < 2^k.
subtask#1 10pts: N <= 20.
subtask#2 20pts : N <= 1000000.
subtask#3 20pts: K <= 20.
subtask#4 50pts: 无特殊限制.

Solution

  • 由于N过大,这是一个强制在线的算法。可以皮一下照搬生成代码
  • 来考虑数量最多的一种书,如果≤(n+1)/2,那一定可以全部读完,反之就需要舍弃
  • 如何在不能记下a[i]的状况下进行判断?可以把书类似两两配对的来处理
  • now记录当前找到重复的书,num记录个数,遇到相同的num+1,不同则num-1。如果生成一个类别时num=0,那么将now更新成a[i],num更新为1
  • 如果没有数量≥(n+1)/2的书,最后num一定等于零
  • 对于有数量≥(n+1)/2的书的情况,再做一遍找出now的具体个数,简单计算即可
  • 当时想了很久没记下a[i]怎么再做一遍

Code

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#define ll long long
int m,k,x[1007],y[1007],z[1007],count[1007],a[1007];
int num,now,H; 
int read(){
    int x=0,f=1;
    char ch=getchar();
    while (!(ch>='0'&&ch<='9')){if (ch=='-') f=-1; ch=getchar();}
    while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
int main(){
    m=read(); k=read();
    for (int i=1;i<=m;i++) count[i]=read();
    for (int i=1;i<=m;i++) x[i]=read();
    for (int i=1;i<=m;i++) y[i]=read();
    for (int i=1;i<=m;i++) z[i]=read();

    int n=0,s=(1<<k)-1;
    for (int i=1;i<=m;i++){
        n++;
        H=x[i];
        if (num==0){now=H; num=1;}
            else if (now==H) num++; else num--;
        //printf("%d ",H);
        ll last=x[i];
        for (int j=1;j<count[i];j++){
            last=(last*y[i]+z[i])&s;
            n++;
            H=last;
            if (num==0){now=H; num=1;}
                else if (now==H) num++; else num--;
        }
    }

    n=0,s=(1<<k)-1; num=0;
    for (int i=1;i<=m;i++){
        n++;
        H=x[i];
        if (H==now) num++;
        ll last=x[i];
        for (int j=1;j<count[i];j++){
            last=(last*y[i]+z[i])&s;
            n++;
            H=last;
            if (H==now) num++;  
        }
    }
    if (num>((n+1)/2)) printf("%d\n",num-(n-num)-1);
        else printf("0\n");
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值