【题意】n个操作(op,x);op == 1时乘上x,op==2时除以输入的第x个操作的x,保证第x都是操作1且每个2中的x不重复。求每次操作之后的值对M取余。
【分析】一直想着乘法逆元,还去找怎么求非素数的逆元可惜有些数不存在逆元,还试过大数计算,然后最大值太大可能是
,足以让任何大数乘法算法TLE,然后就被智商碾压了,再也回不过来了。其实超级简单,用一颗线段树维护1~n个操作的值的乘积,而保证了第x都是操作1且每个2中的x不重复,使得每次除法就是在线段树中删掉第x[i]个数。
【AC CODE】1341ms
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
#define rep(i,a,n) for(int i = a; i < n; i++)
#define repe(i,a,n) for(int i = a; i <= n; i++)
#define per(i,n,a) for(int i = n; i >= a; i--)
#define clc(a,b) memset(a,b,sizeof(a))
const int INF = 0x3f3f3f3f, MAXN = 1e5+10;
LL ret[MAXN<<1], val[MAXN],MOD;
int op[MAXN];
inline int id(int x, int y){return x+y|x!=y;}
void update(int x, int y, int p, int v)
{
if(x == y)
{
ret[id(x,y)] = v;
return;
}
int m = (x+y)>>1;
if(p <= m) update(x,m,p,v);
else update(m+1,y,p,v);
ret[id(x,y)] = ret[id(x,m)]*ret[id(m+1,y)]%MOD;
}
int main()
{
#ifdef SHY
freopen("d:\\1.txt", "r", stdin);
#endif
int t,count = 0;
scanf("%d", &t);
while(t--)
{
int n;
scanf("%d %I64d", &n, &MOD);
repe(i,1,n*2) ret[i] = 1;
printf("Case #%d:\n", ++count);
repe(i,1,n)
{
scanf("%d%I64d", &op[i],&val[i]);
if(1 == op[i])
update(1,n,i,val[i]);
else
update(1,n,val[i],1);
printf("%I64d\n", ret[id(1,n)]);
}
}
return 0;
}