1. 程式人生 > >穀倉(某校老師原創題)

穀倉(某校老師原創題)

題目大意:

          有一個圓形的穀倉,共有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;
}