【BZOJ3672】【UOJ#6】【NOI2014】隨機數生成器

暴力出奇跡ios

原題:數組

2≤N,M≤5000

0≤Q≤50000ide

0≤a≤300ui

0≤b,c≤108spa

0≤x0<d≤1083d

1≤ui,vi≤N×Mcode

 

恩首先容易看出來這個棋盤直接模擬搞出來就好了,不用反演矩陣乘之類的奇怪的東西blog

而後又容易發現只須要遍歷從1~n*m的數儘可能答案裏塞就是最優答案 = =|||ci

而後貪心搞一下,從1~n*m遍歷,對於每個n記錄一個top和一個bottom表示第i行能取第bottom[i]到top[i]列的數get

容易發現暴力維護的複雜度是資瓷的 = =|||

易證不會存在由於以前欽定選擇某些數致使後面選不夠n+m-1個數的狀況

而後暴力搞就能夠辣

由於2.5e7的數組只能開兩個因此有一個要重複使用……

注意答案的長度是2n…………

注意一開始遞推的姿式,好比兩個int和一個longlong相乘要先int乘longlong再乘int之類的

代碼:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<cmath>
 6 using namespace std;
 7 #define ll long long
 8 int rd(){int z=0;  char ch=getchar();
 9     while(ch<'0'||ch>'9')  ch=getchar();
10     while(ch>='0'&&ch<='9'){z=(z<<3)+(z<<1)+ch-'0';  ch=getchar();}
11     return z;
12 }
13 ll a,b,c,d,n,m,o;  int x[25000001];  int nm;
14 int T[25000001],tp[5100],bt[5100];
15 int ans[11000],ast=0;
16 int main(){//freopen("ddd.in","r",stdin);
17     int l,r;
18     cin>>x[0]>>a>>b>>c>>d>>n>>m>>o;  nm=n*m;
19     for(int i=1;i<=nm;++i)  x[i]=((((x[i-1]*a)%d)*x[i-1])%d+(x[i-1]*b)%d+c)%d;
20     for(int i=1;i<=nm;++i)  T[i]=i;
21     for(int i=1;i<=nm;++i)  swap(T[i],T[x[i]%i+1]);
22     while(o--)  l=rd(),r=rd(),swap(T[l],T[r]);
23     for(int i=1;i<=nm;++i)  x[T[i]]=i-1;
24     for(int i=1;i<=n;++i)  tp[i]=m,bt[i]=1;
25     for(int i=1;i<=nm;++i){
26         l=x[i]/m+1,r=x[i]%m+1;
27         if((r>=bt[l])&(r<=tp[l])){
28             for(int j=1;j<l;++j)if(r<tp[j])  tp[j]=r;
29             for(int j=l+1;j<=n;++j)if(r>bt[j])  bt[j]=r;
30             ans[++ast]=i;
31             if(ast==n+m-1)  break;
32         }
33     }
34     for(int i=1;i<ast;++i)   printf("%d ",ans[i]);
35     cout<<ans[ast];
36     return 0;
37 }
View Code
相關文章
相關標籤/搜索