Code Feat UVA11754

中国剩余定理的应用


#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <queue>
#include <algorithm>
#include <vector>
#include <cstring>
#include <stack>
#include <cctype>
#include <utility>   
#include <map>
#include <string>  
#include <climits> 
#include <set>
#include <string> 
#include <sstream>
#include <utility>   
#include <ctime>

using std::priority_queue;
using std::vector;
using std::swap;
using std::stack;
using std::sort;
using std::max;
using std::min;
using std::pair;
using std::map;
using std::string;
using std::cin;
using std::cout;
using std::set;
using std::queue;
using std::string;
using std::istringstream;
using std::make_pair;
using std::greater;
using std::endl;

typedef long long LL;

const int MAXN(110);

template<typename T>
struct SBT
{
	struct NODE
	{
		T key;
		int size;
		NODE *left, *right;
	};

	NODE pool[MAXN];
	NODE *root, *NIL, *rear;
	T tkey;

	void init()
	{
		NIL = pool;
		NIL->left = NIL->right = NIL;
		NIL->size = 0;
		rear = pool+1;
		root = NIL;
	}

	void newnode(NODE *&sour, const T &value)
	{
		rear->key = value;
		rear->size = 1;
		rear->left = rear->right = NIL;
		sour = rear++;
	}

	void left_rotate(NODE *&sour)
	{
		NODE *temp = sour->right;
		sour->right = temp->left;
		temp->left = sour;
		temp->size = sour->size;
		sour->size = sour->left->size+sour->right->size+1;
		sour = temp;
	}

	void right_rotate(NODE *&sour)
	{
		NODE *temp = sour->left;
		sour->left = temp->right;
		temp->right = sour;
		temp->size = sour->size;
		sour->size = sour->left->size+sour->right->size+1;
		sour = temp;
	}

	void maintain(NODE *&sour, bool flag)
	{
		if(flag == false)
		{
			if(sour->left->left->size > sour->right->size)
				right_rotate(sour);
			else
				if(sour->left->right->size > sour->right->size)
				{
					left_rotate(sour->left);
					right_rotate(sour);
				}
				else
					return;
		}
		else
		{
			if(sour->right->right->size > sour->left->size)
				left_rotate(sour);
			else
				if(sour->right->left->size > sour->left->size)
				{
					right_rotate(sour->right);
					left_rotate(sour);
				}
				else
					return;
		}
		maintain(sour->left, false);
		maintain(sour->right, true);
		maintain(sour, false);
		maintain(sour, true);
	}

	void insert(const T &value)
	{
		tkey = value;
		insert_(root);
	}

	void insert_(NODE *&sour)
	{
		if(sour == NIL)
		{
			newnode(sour, tkey);
			return ;
		}
		++sour->size;
		if(tkey < sour->key)
			insert_(sour->left);
		else
			insert_(sour->right);
		maintain(sour, tkey >= sour->key);
	}

	NODE *search(const T &value)
	{
		NODE *sour = root;
		while(sour != NIL && value != sour->key)
		{
			if(value < sour->key)
				sour = sour->left;
			else
				sour = sour->right;
		}
		return sour;
	}
};

void ex_gcd(LL a, LL b, LL &x, LL &y, LL &g)
{
	if(!b)
	{
		g = a;
		x = 1;
		y = 0;
		return ;
	}
	ex_gcd(b, a%b, y, x, g);
	y -= x*(a/b);
}

LL inv(LL a, LL n)
{
	LL ret, temp, g;
	ex_gcd(a, n, ret, temp, g);
	return g == 1LL? (ret+n)%n: -1;
}

LL pow_mod(LL a, LL p, LL n)
{
	LL ret = 1LL;
	for(int i = 0; (1LL << i) <= p; a = a*a%p)
		if(p&(1LL << i))
			ret = ret*a%p;
	return ret;
}

LL china(int n, int *a, int *m)
{
	LL M = 1LL, ret = 0LL, x, y, g;
	for(int i = 0; i < n; ++i)
		M *= m[i];
	for(int i = 0; i < n; ++i)
	{
		LL w = M/m[i];
		ex_gcd(w, m[i], x, y, g);
		ret = (ret+x*w*a[i])%M;
	}
	return (ret+M)%M;
}

int C, S;
int Y[10][100];
int quant[10];
int X[10];
const int LIMIT(10000);

SBT<int> st[10];

void solve_enum(int best)
{
	int count = 0;
	for(int i = 0; i < C; ++i)
		if(i != best)
		{
			st[i].init();
			for(int j = 0; j < quant[i]; ++j)
				st[i].insert(Y[i][j]);
		}
	sort(Y[best], Y[best]+quant[best]);
	for(int i = 0; count != S; ++i)
		for(int j = 0; j < quant[best]; ++j)
		{
			LL temp = Y[best][j]+(LL)X[best]*i;
			if(temp == 0LL)
				continue;
			bool flag = true;
			for(int i = 0; i < C; ++i)
				if(i != best && st[i].search(temp%X[i]) == st[i].NIL)
				{
					flag = false;
					break;
				}
			if(flag)
			{
				printf("%lld\n", temp);
				if(++count == S)
					break;
			}
		}
}

vector<int> ans;
int arr[10];
void dfs(int dep)
{
	if(dep == C)
		ans.push_back(china(C, arr, X));
	else
	{
		for(int i = 0; i < quant[dep]; ++i)
		{
			arr[dep] = Y[dep][i];
			dfs(dep+1);
		}
	}
}

void solve_china()
{
	ans.clear();
	dfs(0);
	sort(ans.begin(), ans.end());
	LL M = 1LL;
	for(int i = 0; i < C; ++i)
		M *= X[i];
	int count = 0;
	for(int i = 0; count != S; ++i)
		for(int j = 0; j < ans.size(); ++j)
		{
			LL temp = ans[j]+M*i;
			if(temp > 0LL)
			{
				printf("%lld\n", temp);
				if(++count == S)
					break;
			}
		}
}

int main()
{
	while(scanf("%d%d", &C, &S), C+S)
	{
		int best = 0, tot = 1;
		for(int i = 0; i < C; ++i)
		{
			scanf("%d%d", X+i, quant+i);
			for(int j = 0; j < quant[i]; ++j)
				scanf("%d", Y[i]+j);
			if(quant[i]*X[best] < quant[best]*X[i])
				best = i;
			tot *= quant[i];
		}
		if(tot > LIMIT)
			solve_enum(best);
		else
			solve_china();
		putchar('\n');
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值