这道题绝对不算难,但题面确实让我理解了半天,也算是长了见识把。
原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=5995
Kblack loves flag
Accepts: 422
Submissions: 765
Time Limit: 2000/1000 MS (Java/Others)
Memory Limit: 65536/65536 K (Java/Others)
问题描述
kblack喜欢旗帜(flag),他的口袋里有无穷无尽的旗帜。某天,kblack得到了一个n?m的方格棋盘,他决定把k面旗帜插到棋盘上。每面旗帜的位置都由一个整数对(x,y)来描述,表示该旗帜被插在了第x行第y列。插完旗帜后,kblack突然对那些没有插过旗帜的行和列很不满,于是他想知道,有多少行、列上所有格子都没有被插过旗帜。kblack还要把妹,于是就把这个问题丢给了你,请你帮他解决。
输入描述
由于本题输入数据较大,所以采取在程序内生成数据的方式。随机数产生器中有个内部变量x初始时为seed,seed是我们提供的随机种子。每次请求生成一个[l,r]内的随机数时,它会将x变为(50268147x+6082187) mod 100000007,然后返回x mod (r?l+1)+l。输入包含多组数据。第一行有一个整数T,表示测试数据的组数,对于每组数据:输入一行3个整数n,m,k,seed分别表示棋盘的行数、列数、棋盘上旗帜的面数、随机种子。接下来,你需要按顺序生成k面旗帜的位置信息。对于每面旗帜,依次生成一个[1,n]内的随机数和一个[1,m]内的随机数,分别表示x,y。如果你无法理解数据生成的过程,你可以复制以下代码并调用Init函数来生成数据(限C++选手)。` const int _K=50268147,_B=6082187,_P=100000007; int _X; inline int get_rand(int _l,int _r){_X=((long long)_K*_X+_B)%_P;return _X%(_r-_l+1)+_l; } int n,m,k,seed; int x[1000006],y[1000006]; void Init(){scanf("%d%d%d%d",&n,&m,&k,&seed);_X=seed;for (int i=1;i<=k;++i)x[i]=get_rand(1,n),y[i]=get_rand(1,m); } `(1≤T≤7),(1≤n,m≤1000000),(0≤k≤1000000),(0≤seed<100000007)
输出描述
对于每组测试数据输出一行2个整数,分别表示没有被插过旗帜的行、列数目。
输入样例
2 4 2 3 233 3 4 4 2333
输出样例
2 1 1 0
Hint
第1组数据的旗帜的位置依次为:(4,2),(1,2),(1,2)第2组数据的旗帜的位置依次为:(2,1),(2,3),(3,4),(3,2)
思路:
将插过旗子的行和列全部标记出来,最后遍历数个数就行了。
代码:
#include<iostream>
#include<cstring>
using namespace std;const int _K=50268147,_B=6082187,_P=100000007;
int _X;
inline int get_rand(int _l,int _r)
{_X=((long long)_K*_X+_B)%_P;return _X%(_r-_l+1)+_l;
}int n,m,k,seed;
int x[1000006],y[1000006];
void Init()
{cin>>n>>m>>k>>seed;_X=seed;for(int i=1;i<=k;++i){x[i]=get_rand(1,n);y[i]=get_rand(1,m);
// cout<<x[i]<<" "<<y[i]<<endl;}
// cout<<endl;}void find(){bool x_1[1000006],y_1[1000006];memset(x_1,true,sizeof(x_1));memset(y_1,true,sizeof(y_1));int count_1=0,count_2=0;for(int i=1;i<=k;++i) {x_1[x[i]]=false;y_1[y[i]]=false;}for(int i=1;i<=n;++i)if(x_1[i]) ++count_1;for(int i=1;i<=m;++i)if(y_1[i]) ++count_2;cout<<count_1<<" "<<count_2<<endl;}int main()
{ios::sync_with_stdio(false);int T;cin>>T;while(T--){memset(x,0,sizeof(x));memset(y,0,sizeof(y));Init();find();}return 0;
}