穀倉(某校老師原創題)
阿新 • • 發佈:2018-12-26
題目大意:
有一個圓形的穀倉,共有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; }