BestCoder Round #90 Kblack loves flag


BestCoder Round #90 Kblack loves flag

问题描述
kblack喜欢旗帜(flag),他的口袋里有无穷无尽的旗帜。
某天,kblack得到了一个n∗mn*mnm的方格棋盘,他决定把kkk面旗帜插到棋盘上。
每面旗帜的位置都由一个整数对(x,y)\left(x,y \right)(x,y)来描述,表示该旗帜被插在了第xxx行第yyy列。
插完旗帜后,kblack突然对那些没有插过旗帜的行和列很不满,于是他想知道,有多少行、列上所有格子都没有被插过旗帜。
kblack还要把妹,于是就把这个问题丢给了你,请你帮他解决。
输入描述
由于本题输入数据较大,所以采取在程序内生成数据的方式。
随机数产生器中有个内部变量xxx初始时为seedseedseedseedseedseed是我们提供的随机种子。每次请求生成一个[l,r]\left[l,r \right][l,r]内的随机数时,它会将xxx变为(50268147x+6082187) mod 100000007\left(50268147x+6082187\right)\ mod\ 100000007(50268147x+6082187) mod 100000007,然后返回x mod (r−l+1)+lx\ mod\ \left(r-l+1 \right)+lx mod (rl+1)+l。
输入包含多组数据。第一行有一个整数TTT,表示测试数据的组数,对于每组数据:
输入一行3个整数nnnmmmkkkseedseedseed分别表示棋盘的行数、列数、棋盘上旗帜的面数、随机种子。
接下来,你需要按顺序生成k面旗帜的位置信息。
对于每面旗帜,依次生成一个[1,n]\left[1,n \right][1,n]内的随机数和一个[1,m]\left[1,m \right][1,m]内的随机数,分别表示xxxyyy。
如果你无法理解数据生成的过程,你可以复制以下代码并调用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)\left(1\leq T\leq 7 \right)(1T7)(1≤n,m≤1000000)\left(1\leq n,m\leq 1000000 \right)(1n,m1000000)(0≤k≤1000000)\left(0\leq k\leq 1000000 \right)(0k1000000)(0≤seed<100000007)\left(0\leq seed<100000007 \right)(0seed<100000007)
输出描述
对于每组测试数据输出一行2个整数,分别表示没有被插过旗帜的行、列数目。
输入样例
2
4 2 3 233
3 4 4 2333
输出样例
2 1
1 0
Hint
第1组数据的旗帜的位置依次为:(4,2)\left(4,2\right)(4,2),(1,2)\left(1,2\right)(1,2),(1,2)\left(1,2\right)(1,2)

第2组数据的旗帜的位置依次为:(2,1)\left(2,1 \right)(2,1),(2,3)\left(2,3\right)(2,3),(3,4)\left(3,4\right)(3,4),(3,2)\left(3,2\right)(3,2)
 
一开始直接用set保存旗帜的位置结果超时了,然后换成用vector储存,输入完成后排一下序,以行为例,定义vector<int>x,x中的最大值减去x中不重复出现的整数的个数,比如x={1,1,1,2,3,4,6},那么x中不重复出现的整数的个数为5,最大值为6,6-5=1也就是没有插旗帜的总行数
AC代码:
#include<cstdio>
#include<iostream>
#include<math.h>
#include<string>
#include<vector>
#include<algorithm>
#include<set>
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;

void Init() {
	scanf("%d%d%d%d", &n, &m, &k, &seed);
	vector<int> x, y;
	_X = seed;
	for (int i = 1; i <= k; ++i)
	{
		x.push_back(get_rand(1, n));
		y.push_back(get_rand(1, m));
	}
	sort(x.begin(), x.end());
	sort(y.begin(), y.end());
	int temx=1, temy=1;
	for (vector<int>::size_type i=1; i < x.size(); i++)
	{
		if (x[i] != x[i - 1])
			temx++;
	}
	for (vector<int>::size_type i = 1; i < y.size(); i++)
	{
		if (y[i] != y[i - 1])
			temy++;
	}
	cout << x[x.size() - 1] - temx << " " << y[y.size() - 1] - temy << endl;
}


int main()
{
	int i;
	cin >> i;
	while (i--)
	{
		Init();
	}
	return 0;
}

 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值