您的位置:首页 > 其它

解题报告 之 HDU5475 An easy problem

2015-09-28 16:46 369 查看


解题报告 之 HDU5475 An easy problem

Description

One day, a useless calculator was being built by Kuros. Let's assume that number X is showed on the screen of calculator. At first, X = 1. This calculator only supports two types of operation.

1. multiply X with a number.

2. divide X with a number which was multiplied before.

After each operation, please output the number X modulo M.



Input

The first line is an integer T(











),
indicating the number of test cases.

For each test case, the first line are two integers Q and M. Q is the number of operations and M is described above. (





























)

The next Q lines, each line starts with an integer x indicating the type of operation.

if x is 1, an integer y is given, indicating the number to multiply. (













)

if x is 2, an integer n is given. The calculator will divide the number which is multiplied in the nth operation. (the nth operation must be a type 1 operation.)

It's guaranteed that in type 2 operation, there won't be two same n.



Output

For each test case, the first line, please output "Case #x:" and x is the id of the test cases starting from 1.

Then Q lines follow, each line please output an answer showed by the calculator.



Sample Input

1
10 1000000000
1 2
2 1
1 2
1 10
2 3
2 4
1 6
1 7
1 12
2 7




Sample Output

Case #1:
2
1
2
20
10
1
6
42
504
84




Source

2015 ACM/ICPC Asia Regional Shanghai Online

题目大意:有一个数X,初始状态为1。给出两种操作,操作1是在现有的数上乘上一个数 y,操作2是除以一个之前已经乘过的某个数。注意操作2绝不会除以一个乘过的数两次。要求每次操作后输出X % M 的值。注意有1e5次操作,0<=y<=1e9。

分析:首先注意题目的描述,只有输出的时候才取模,这里一定要看清楚,不然就是千年WA。很自然的想法是直接硬上,每次都维护一下X的值,不过很容易发现这是不现实的,因为根本存不下那么大的数……然后又会很自然的想到把X表示为乘数 ∏yi
。但是又很明显发现时间复杂度是超过的,因为查询次数1e5。

于是乎必须要有一个log级别的算法。于是乎我组大神机智的想到了线段树(其实我也想到了线段树但是没有理智的分析复杂度。。。)。具体思路是,因为操作数为1e5,那么最多有1e5个乘数,首先假设他们都是1。操作1更新对应的节点为yi,操作2更新对应的节点为1。再由于乘法和取模的可交换性。所以节点的value表示取模后的结果即可。(为什么不用线段树就不能直接存取模后的值,原因在于用了线段树之后,通过将yi变为1后重新乘一次,将除法转为乘法,解决了除法和取模的不可交换性。)

每次操作直接输出root的value即可。还有一个坑点在于叶结点赋值yi时也要取模,血的教训。

上代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 10;
ll tree[maxn * 4];
ll M, X = 1;

void pushUp( int v )
{
	tree[v] = tree[v << 1] * tree[(v << 1) + 1] % M;
}

void built( int v, int l, int r )
{
	if(l == r)
	{
		tree[v] = 1;
		return;
	}
	int mid = (l + r) >> 1;
	built( v << 1, l, mid );
	built( (v << 1) + 1, mid + 1, r );
	pushUp( v );
}

void update( int v, int l, int r, int idx, ll val )
{
	if(l == r)
	{
		tree[v] = val%M;
		return;
	}
	int mid = (l + r) >> 1;
	if(idx <= mid)
	{
		update( v << 1, l, mid, idx, val );
	}
	else
	{
		update( (v << 1) + 1, mid + 1, r, idx, val );
	}
	pushUp( v );
}

int main()
{
	int T;
	cin >> T;
	for(int kas = 1; kas <= T; kas++)
	{
		ll Q;
		X = 1;
		scanf( "%I64d %I64d", &Q, &M );
		printf( "Case #%d:\n", kas );
		built( 1, 1, Q );
		for(int k = 1; k <= Q; k++)
		{
			ll opt, ind;
			scanf( "%I64d %I64d", &opt, &ind );
			if(opt == 1)
			{
				update( 1, 1, Q, k, ind );
			}
			if(opt == 2)
			{
				update( 1, 1, Q, ind, 1 );
			}
			X = tree[1];
			printf( "%I64d\n", X );
		}

	}
	return 0;
}


就是这样拉~~膜拜一下新队友叔叔,简直是思维大神,仰视之~
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: