解题:NOI 2014 随机数生成器

题面

为什么NOI2014有模拟题=。=???

按题意把序列生成出来之后,对每一行维护一个能取到的最左侧和能取到的最右侧。从小到大$O(n^2)$枚举数字看看能否填入,能填入则暴力$O(n)$更新信息,因为能填入的总共只有$n+m$级别个数的数,所以复杂度没问题

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 const int N=5005,inf=1e9;
 6 int d,n,m,q,nm,t1,t2,s[4];
 7 int x[N*N],p[N*N],ll[N],rr[N];
 8 void Add(int &x,int y)
 9 {
10     x+=y;
11     if(x>=d) x-=d;
12 }
13 bool Able(int o)
14 {
15     int x=(o-1)/m+1,y=o%m; if(!y) y=m;
16     if(y>=ll[x]&&y<=rr[x]) 
17     {
18         for(int i=1;i<x;i++) rr[i]=min(rr[i],y);
19         for(int i=x+1;i<=n;i++) ll[i]=max(ll[i],y);
20         return true;
21     }
22     return false;
23 }
24 int main()
25 {
26     scanf("%d%d%d%d%d",&x[0],&s[1],&s[2],&s[3],&d);
27     scanf("%d%d%d",&n,&m,&q),nm=n*m;
28     for(int i=1;i<=nm;p[i]=i,i++)
29         for(int j=3,t=1;j;t=1ll*t*x[i-1]%d,j--)
30             Add(x[i],1ll*t*s[j]%d);
31     for(int i=1;i<=nm;i++) swap(p[i],p[x[i]%i+1]);
32     for(int i=1;i<=q;i++)
33         scanf("%d%d",&t1,&t2),swap(p[t1],p[t2]);
34     for(int i=1;i<=n*m;i++) x[p[i]]=i;
35     for(int i=1;i<=n;i++) ll[i]=1,rr[i]=m;
36     for(int i=1;i<=nm;i++)
37         if(Able(x[i])) printf("%d ",i);
38     return 0;
39 }
View Code
原文地址:https://www.cnblogs.com/ydnhaha/p/10432139.html