[SDOI2019]快速查询(乘法逆元)

这怕不是SDOI R2最水的一年吧……不过我看了day1,只会做这一题……

根本没什么算法,乘法逆元是我硬加上去的。看完这题,感觉,这是R2?

不过看SD省选成绩,这题人均切,但坑了几位高手倒是真的……

不BB了。写题解:很容易想到记录两个变量add和mul,然后表示当前数x,变为mul*x+add即为实际数字,然后直接根据题意暴力修改即可:对于1操作,将a[i]修改为(val-add)mul-1,对于2操作,add+=val,对于3操作,mul*=val,add*=val,对于4操作,mul=0,add=val,对于5操作,直接回答即可,对于6操作,修改时记录即可。复杂度O(tq),看上去是不是很对啊?

实际上,这显然是错的……因为对于1操作,mul为0时,根本无法确定mul-1,于是直接GG(讲真的这样连样例都过不了),要使mul≠0。那怎么办呢?将进行共至少1次1操作的变量单独提出来为v[i],然后再记录一个v[0]表示不存在1操作的变量。然后每个数记录时间戳tim[i],表示最近一次单独修改的时间,再记录一个last表示近一次整体修改的时间。初始化mul=1,add=0,1、2、3、6操作一样处理,4操作,v[0]=val,mul=1,add=0,last=t(其中t表示第t次操作);5操作,若为没进行过单独修改的变量,或者tim[i]<=last,则视为mul*v[0]+add,反之为mul*v[i]+add。复杂度O(tq)。

注意事项:

1、不能暴力求逆元,不要认为O(tqlog)能通过本题(虽然可能的确能通过),注意:mod=1e7+19,预处理inv[1...mod-1]即可。

2、对于3操作,若乘的数为0,则应该转为4操作。

3、对于1操作存在的变量,我们用容易写的map记录时,切记初始化时就要将1和5操作里的i修改为map中的id,否则仍然会退化为O(tqlog)

本题考查点在于选手对细节的处理(防止变为O(tqlog)或许不会导致TLE)和对特殊情况的判断(防止细节上WA)

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+7,mod=1e7+19;
struct node{int op,x,y;}q[N];
unordered_map<int,int>mp;
int n,m,Q,t,mul,add,ans,sum,last,a[N],b[N],v[N],tim[N],inv[N*100];
void work(int i,int t)
{
    if(q[i].op==6)ans=(ans+sum)%mod;
    else if(q[i].op==2)sum=(sum+1ll*n*q[i].x)%mod,add=(add+q[i].x)%mod;
    else if(q[i].op==3)sum=1ll*sum*q[i].x%mod,mul=1ll*mul*q[i].x%mod,add=1ll*add*q[i].x%mod;
    else if(q[i].op==4)sum=1ll*n*q[i].x%mod,last=t,mul=1,add=0,v[0]=q[i].x;
    else if(q[i].op==5)
    {
        if(tim[q[i].x]<=last)ans=(ans+1ll*mul*v[0]+add)%mod;
        else ans=(ans+1ll*mul*v[q[i].x]+add)%mod;
    }
    else{
        if(tim[q[i].x]<=last)sum=(sum-1ll*mul*v[0]%mod-add+2*mod)%mod;
        else sum=(sum-1ll*mul*v[q[i].x]%mod-add+2*mod)%mod;
        sum=(sum+q[i].y)%mod,tim[q[i].x]=t,v[q[i].x]=1ll*(q[i].y-add+mod)*inv[mul]%mod;
    }
}
int main()
{
    scanf("%d%d",&n,&Q);
    inv[1]=1;for(int i=2;i<mod;i++)inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod;
    for(int i=1;i<=Q;i++)
    {
        scanf("%d",&q[i].op);
        if(q[i].op!=6)scanf("%d",&q[i].x);
        if(q[i].op==1)
        {
            scanf("%d",&q[i].y);
            q[i].y=(q[i].y%mod+mod)%mod;
            if(!mp[q[i].x])mp[q[i].x]=++m;
        }
        else if(q[i].op<=4)q[i].x=(q[i].x%mod+mod)%mod;
        if(q[i].op==3&&!q[i].x)q[i].op=4;
    }
    for(int i=1;i<=Q;i++)if(q[i].op==1||q[i].op==5)q[i].x=mp[q[i].x];
    mul=1;
    scanf("%d",&t);
    for(int i=1;i<=t;i++)scanf("%d%d",&a[i],&b[i]);
    for(int i=1;i<=t*Q;i++)
    {
        int x=(i-1)/Q+1,y=(i-1)%Q+1;
        work((a[x]+1ll*y*b[x])%Q+1,i);
    }
    printf("%d",ans);
}
View Code

猜你喜欢

转载自www.cnblogs.com/hfctf0210/p/10824947.html
今日推荐