谷仓(某校老师原创题)

题目大意:

          有一个圆形的谷仓,共有n个房间,按顺时针编号从1到n。现在有许多头奶牛,他们都有自己最喜欢的一个房间。傍晚回家时,奶牛们去找自己最喜欢的房间。如果发现被占了,他们就会按照顺时针方向找第一个空闲的房间住进去。现在请你输出最小的空闲的房间号。注意,这个答案和奶牛们回家的顺序是无关的。2<=n<=3000000,1<=k<=10000,A,B的值在区间[0,10^9]。

    一看就是去改编的……

输入

输入格式:

第一行两个整数n,k。

接下来有k行。每行4个整数,x,y,a,b.表示有x头奶牛喜欢f[1],f[2]……,f[y]。其中f[i]=(a*i+b)%n+1.

输出

输出格式:

输出最小的空闲房间号。

样例输入

10 3
3 2 2 4
2 1 0 1
1 1 1 7

样例输出

6

重难点思想:

    首先先要理解到这道题的意思,是说每一行喜欢f[i]的房间都有x头奶牛,理解到这一步后,就可以从无从下手到RE。

    再来分析,由于我们的a ,b 很大,所以有可能会爆long long , 即使这里有余数还是会爆,故,我们要模三次:

int js( int i ){
    long long sum =( ( i * s ) % n + b % n ) % n;
    int k = sum % n;
    return k + 1;
}

   然后就可以从RE晋升到TLE……

  我们现在来优化模拟的方法:

   用最简单的贪心来想,我们只让第i个房间保留1头奶牛,其余的全都移到下一个房间中,这样虽然一遍解决不了,但是跑2*n就可以把所有牛都放进去,最后再找空余的即可。

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
int n , m;
long long s , b , x , y;
long long a[3000003];
int js( int i ){
    long long sum =( ( i * s ) % n + b % n ) % n;
    int k = sum % n;
    return k + 1;
}
void read( long long &x ){
    int f = 1; x = 0;
    char s = getchar();
    while( s < '0' || s > '9' ){
        if( s == '-' )
            f = -1;
        s = getchar();
    }
    while( s >= '0' && s <= '9' ){
        x = x * 10 + s - '0';
        s = getchar();
    }
    x *= f;
}
int main(){
    scanf( "%d%d" , &n , &m );
    for( int i = 1 ; i <= m ; i ++ ){
        read( x );
        read( y );read( s );read( b );
        for( int j = 1 ; j <= y ; j ++ )
            a[js( j )] += x;
    }
    for( int j = 1 ; j <= 3 ; j++ ){
        for( int i = 1 ; i <= n ; i ++ ){
            if( a[i] > 1 ){
                if( i == n )
                    a[1] += a[n] - 1;
                else
                    a[ i + 1 ] += a[i] - 1;
                a[i] = 1;
            }
        }
    }
 
    for( int i = 1 ; i <= n ; i ++ )
        if( a[i] == 0 ){
            printf( "%d" , i );
            return 0;
        }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43823476/article/details/85260607