题意简述
你有一个数
x
x
x,支持两种操作:
1 m
:执行x*=m
,并输出x%mod
(long long
能存下,mod
不一定为质数)
2 pos
:x/=第pos次乘的m
,保证第pos
次是1
操作,输出x%mod
处理一些这样的操作。
思路
1
操作很好做。2
操作。。。看起来就是维护一个数组存一下每次乘了几,然后除对应位置的数即珂。
珂是,什么阻挡了我们的计算?
- 要膜
- 膜数mod不一定是质数!(所以没法用逆元)
f ∗ ∗ k f**k f∗∗k。所以我们要另外想一个办法。我们还是维护那个数组,对于除的操作,我们就把第 p o s pos pos个位置改成 1 1 1,对于乘的操作,我们就把第 i i i个位置改成 m m m( i i i表示这次操作是第 i i i次操作),然后输出的时候,就询问整体的和即珂。
那么如何加速询问整体的和呢?线段树。
然后这个题就变成了一个单点修改,整体查询的水题了。由于是整体查询,你甚至不用写
Q
u
e
r
y
Query
Query函数,只要输出线段树上第一个位置的
s
u
m
sum
sum值即珂。
代码:
#include<bits/stdc++.h>
using namespace std;
namespace Flandle_Scarlet
{
#define N 100100
#define int long long
int q,mod;
void R1(int &x)
{
x=0;char c=getchar();int f=1;
while(c<'0' or c>'9') f=(c=='-')?-1:1,c=getchar();
while(c>='0' and c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
x=(f==1)?x:-x;
}
void Input()
{
R1(q),R1(mod);
}
class SegmentTree
{
public:
struct node
{
int l,r;
int s;
}tree[N<<2];
#define ls index<<1
#define rs index<<1|1
#define L tree[index].l
#define R tree[index].r
#define S tree[index].s
#define lL tree[ls].l
#define lR tree[ls].r
#define lS tree[ls].s
#define rL tree[rs].l
#define rR tree[rs].r
#define rS tree[rs].s
void Update(int index)
{
S=(lS*rS)%mod;
}
void BuildTree(int l,int r,int index)
{
L=l,R=r,S=1;
if (l==r) return;
int mid=(l+r)>>1;
BuildTree(l,mid,ls);
BuildTree(mid+1,r,rs);
Update(index);
}
void Change1(int pos,int x,int index)
{
if (pos<L or R<pos) return;
if (L==R) return (void)(S=x%mod);
Change1(pos,x,ls);
Change1(pos,x,rs);
Update(index);
}
}T;
int ccnt=0;//change cnt
vector<int>changes;//positions of changes
void Soviet()
{
T.BuildTree(1,q,1);
for(int i=1;i<=q;++i)
{
int o;R1(o);
if (o==1)
{
int m;R1(m);
m%=mod;
T.Change1(i,m,1);
printf("%lld\n",T.tree[1].s%mod);
}
else if (o==2)
{
int pos;R1(pos);
T.Change1(pos,1,1);
printf("%lld\n",T.tree[1].s%mod);
}
}
}
void IsMyWife()
{
if (0)
{
freopen("","r",stdin);
freopen("","w",stdout);
}
int t;R1(t);
while(t--)
{
Input();
Soviet();
}
}
#undef int //long long
};
int main()
{
Flandle_Scarlet::IsMyWife();
return 0;
}