HDU 5475 (暴力or线段树)-An easy problem

题目:

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(1≤T≤101≤T≤10), 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. (1≤Q≤105,1≤M≤1091≤Q≤105,1≤M≤109) 
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. (0<y≤1090<y≤109) 
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

题目大意:有T组测试样例,每个样例给出n个操作,起始值为sum=1,每个操作对应两个数 x y,当x==1时,用当前的sum值乘以y;当x==2时,用当前的sum值除以第x次操做乘的那个值。每次操作,输出一次结果,注意最后结果要对m取余。

思路:对于乘法来说简单,因为遵循同余法则。注意除法不遵循同余法则。但是有些结果没法表示,再进行除法运算。

可以这样考虑,开一个数组a[],对于第x次操作,若x==1,则a[x]=y;若x==2,则a[x]=1,并且a[y]=1,然后再从第一个依次乘,这样就可得到结果。

 

暴力法代码(没想到能过,不超时)。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<map>
#include<set>
#include<stack>
#include<queue>
#include<vector>
#define ll long long
using namespace std;
int t;
int q;
const int INF=1e5+5;
int m;
ll sum;
int a[INF];
int main()
{
    cin>>t;
    int s=0;
	while(t--)
	{
		s++;
		sum=1;
        scanf("%d%d",&q,&m);
		int i,j,k,l;
		printf("Case #%d:\n",s);
		for(i=1;i<=q;i++)
		{
			scanf("%d%d",&j,&k);
			if(j==1){
				sum=sum*k%m;
				a[i]=k;
				printf("%d\n",sum);
			}
			else{//很关键
				a[k]=1;a[i]=1;
				sum=1;
				for(l=1;l<=i;l++)
				{
					sum=sum*a[l]%m;
				}
				printf("%d\n",sum);
			}
		}		
	}    	
	return 0;
} 

 

线段树:思路也是那样,只是将那个过程转化到线段树中去了。

AC代码:

#include<iostream>//注意用long long 型,int型没过
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<map>
#include<set>
#include<stack>
#include<queue>
#include<vector>
#define ll long long
using namespace std;
int t;
ll q,m;
const int INF=1e5+5;
struct node{
	ll left;
	ll right;
	ll sum;
}f[4*INF];
void build(ll ans,ll l,ll r){
	f[ans].left =l;f[ans].right =r;
	f[ans].sum =1;
	if(l==r)return;
	ll mid=(l+r)/2;
	build(ans<<1,l,mid);
	build(ans<<1|1,mid+1,r);
}
void update(ll ans,ll l,ll x){
	if(f[ans].left ==l&&f[ans].right ==l)
	{
		f[ans].sum =x%m;return;
	}
	ll mid=(f[ans].left +f[ans].right )/2;
	if(l<=mid)update(ans<<1,l,x);
	else {
		update(ans<<1|1,l,x);
	}
	f[ans].sum =f[ans<<1].sum*f[ans<<1|1].sum%m; 
}
ll getsum(ll ans,ll l,ll r)
{
	if(f[ans].left ==l&&f[ans].right ==r)
	{
		return f[ans].sum ;
	}
	ll mid=(f[ans].left +f[ans].right )/2;
	if(r<=mid){
		return getsum(ans<<1,l,r);
	}
	else if(l>mid)
	{
		return getsum(ans<<1|1,l,r);
	}
	else {
		return getsum(ans<<1,l,mid)*getsum(ans<<1|1,mid+1,r)%m;
	}
}
int main()
{
	int s=0;
	cin>>t;
	while(t--)
	{
		s++;
		scanf("%lld%lld",&q,&m);
		build(1,1,q);
		ll i,j,k;
		ll val;
		printf("Case #%d:\n",s);
		for(i=1;i<=q;i++)
		{
		    scanf("%lld%lld",&j,&k);
			if(j==1)
			{
		                update(1,i,k);
				val=getsum(1,1,i);	
				printf("%lld\n",val);	
			}	
			else {
				update(1,k,1);
				val=getsum(1,1,i);
				printf("%lld\n",val);
			}
		}
	}
	return 0;
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值