NOI2018屠龙勇士(扩展CRT + splay(multiset))

这里写图片描述
这里写图片描述
这里写图片描述

QWQ 一到假期就颓废 哎

今年新鲜出炉的NOI题,QwQ同步赛的时候写的,后来交了一发洛谷,竟然过了

首先 根据题目,我们很容易得到,假设对应每一条龙的剑的攻击力是 a t k 的话

a i x × a t k + k p i = 0

x × a t k = a i ( mod p i )

QwQ一看到这个式子,就想到了扩展crt求解。

不过我一开始的想法是,根据扩欧,求 a i x × a t k + k p i = 0 中的每一个 x 的通解表达式,然后把它写成同余的形式,最后再用扩展CRT合并

但是因为有点麻烦 所以没写

这里提供 w a s n 爷的做法

就是通过求逆元,直接把 a t k 弄到等式的右边

只有当一个数和模数互质,他们才会有逆元

我们知道

a i x × a t k + k p i = 0

所以
a i = x × a t k + k p i

然后这个方程有解的条件是 a i | g c d ( a t k , p i )

那么我们先把等式两边同时除以 g c d ( a t k , p i ) ,再写成同余式子的形式

x × a t k g c d = a i g c d ( mod p i g c d )

此时 a t k g c d p i g c d 是互质的,所以一定存在逆元,然后就可以化成扩展crt的形式,之后求解就行

至于每一次确定 a t k 的过程,只需要一颗平衡树就行,不过要注意,可能会存在重复的元素,所以理论上不能用 s e t

哦对!一个重要的事情!

在crt和一开始乘逆元的过程中,会爆long long,所以需要快速乘来进行乘法!这里一定要注意!
以后遇到这种题,要想到快速乘!

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#define ll long long

using namespace std;

inline ll read()
{
  ll x=0,f=1;char ch=getchar();
  while (!isdigit(ch)) {if (ch=='-') f=-1;ch=getchar();}
  while (isdigit(ch)) {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
  return x*f;
}

const int maxn = 3e5+1e2;

ll lif[maxn],p[maxn],a[maxn],m[maxn];
ll atk[maxn];

ll sz[maxn],ch[maxn][4],fa[maxn];
ll cnt[maxn],size=2,n,mm,root,t;
ll val[maxn];
ll jiangli[maxn];
bool flag=true;

ll mul(ll i,ll j,ll p)
{
    ll ans=0;
    while (j){
        if (j&1) ans=(ans+i)%p;
        i=(i+i)%p;
        j>>=1;
    }
    return ans;
}

ll son (ll x)
{
    if (x==ch[fa[x]][0]) return 0;
    else return 1;
}

void update(ll x)
{
    sz[x]=sz[ch[x][0]]+sz[ch[x][1]]+cnt[x];
}

void rotate(ll x)
{
    ll y=fa[x],z=fa[y];
    ll b=son(x),c=son(y);
    ch[z][c]=x;
    fa[x]=z;
    ch[y][b]=ch[x][!b];
    fa[ch[x][!b]]=y;
    ch[x][!b]=y;
    fa[y]=x;
    update(y);
    update(x);
}

void splay(ll x,ll p)
{
    while (fa[x]!=p)
    {
        ll y=fa[x],z=fa[y];
        if (z==p) rotate(x);
        else
        if (son(x)==son(y))
        {
            rotate(y);
            rotate(x);
        }
        else
        {
            rotate(x);
            rotate(x);
        }
    }
    if (fa[x]==0) root=x;
}

ll find_qq(ll x)
{
    ll now = root,num=0;
    while (now)
    {
        if (val[now]<x)
        {
            num=now;
            now=ch[now][1];
        }
        else
          now=ch[now][0];
    }
    return num;
}

ll find_hj(ll x)
{
    ll now = root,num=0;
    while (now)
    {
        if (val[now]>x)
        {
            num=now;
            now=ch[now][0];
        }
        else
          now=ch[now][1];
    }
    return num;
}

void insert(ll x)
{
    ll qq=find_qq(x);
    ll hj=find_hj(x);
    splay(qq,0);
    splay(hj,qq);
    ll y=ch[hj][0];
    if (cnt[y])
      cnt[y]++,update(y);
    else
    {
        size++;
        fa[size]=hj;
        cnt[size]=1;
        val[size]=x;
        sz[size]=1;
        ch[hj][0]=size;
        splay(size,0);
    }
}

void delet(ll x)
{
    ll qq=find_qq(x);
    ll hj=find_hj(x);
    splay(qq,0);
    splay(hj,qq);
    ll y=ch[hj][0];
    if (cnt[y]>1)
      cnt[y]--,update(y);
    else
    {
        fa[y]=0;
        cnt[y]=0;
        val[y]=0;
        sz[y]=0;
        ch[hj][0]=0;
    }
}

ll gcd(ll a,ll b)
{
    if (b==0) return a;
    else return gcd(b,a%b);
}

ll exgcd(ll &x,ll &y,ll a,ll b)
{
    if (b==0)
    {
        x=1;
        y=0;
        return a;
    }
    ll cnt = exgcd(x,y,b,a%b);
    ll tmp = x;
    x=y;
    y=tmp-a/b*y; 
    return cnt;
}

void init()
{
    memset(ch,0,sizeof(ch));
    memset(sz,0,sizeof(sz));
    memset(fa,0,sizeof(fa));
    memset(val,0,sizeof(val));
    memset(a,0,sizeof(a));
    memset(m,0,sizeof(m));
    val[1]=1e18;
    val[2]=-1e18;
    fa[2]=1;
    ch[1][0]=2;
    root=1;
    size=2;
    flag=true;
}

ll niyuan(ll num,ll p)
{
    ll ymh,szh;
    exgcd(ymh,szh,num,p);
    ymh=(ymh%p+p)%p;
    return ymh;
}

ll count(ll x)
{
    ll hj=find_qq(x+1);
    if (val[hj]==-1e18){
        ll ii = val[find_hj(val[hj])];
        delet(ii);
        return ii;
    }
    else
    {
      ll ii = val[hj];
      delet(ii);
      return ii;
    }
}

void solve1()
{
    for (int i=1;i<=n;i++)
    {
        ll tmp = count(lif[i]);
        //cout<<tmp<<endl;
        ll gcd1=gcd(tmp,p[i]);
    //  cout<<gcd1<<endl;
        m[i]=p[i]/gcd1;
        if (lif[i]%gcd1!=0) flag=false;
        if (!flag) return;
        lif[i]=lif[i]/gcd1;
        a[i]=mul(lif[i],niyuan(tmp/gcd1,m[i]),m[i]);
        insert(jiangli[i]);
    }
}

long long solve()
{
    ll x0=0,M=0; 
    x0=a[1];
    M=m[1];
    long long x=0,y=0;
    for (int i=2;i<=n;i++)
    {
        ll gcd1=exgcd(x,y,M,m[i]);
        if ((a[i]-x0)%gcd1!=0) flag=false;
        if (!flag) return -1;
        long long tmp = m[i]/gcd1;
        ll yyy=(a[i]-x0)/gcd1;
        yyy%=tmp;
        if (yyy<=0) yyy+=tmp;
        x=(x%tmp+tmp)%tmp; 
        x=mul(x,yyy,tmp); 
        ll ppp = M; 
        M=M/gcd1*m[i];
        ppp=(ppp%M+M)%M;
        x0=(mul(x,ppp,M)+x0%M)%M;
    }
    x0=(x0+M)%M;
    if (x0==0) x0+=M;
    return x0;
}

void solve3()
{
    //cout<<"gg"<<endl;
    ll ans=-1e9;
    for (int i=1;i<=n;i++)
    {
        ll tmp = count(lif[i]);
        ll cnt = lif[i]/tmp;
        lif[i]=lif[i]%tmp;
        if (lif[i]>0) cnt++;
        ans=max(ans,cnt);
        insert(jiangli[i]);
    }
    cout<<ans<<endl;
}

int main()
{ 
  //freopen("dragon.in","r",stdin);
  //freopen("dragon.out","w",stdout);
  cin>>t;
  while (t--)
  {
     init();
     n=read(),mm=read();
     int now = 0;
     for (int i=1;i<=n;i++) lif[i]=read();
     for (int i=1;i<=n;i++) 
       {
          p[i]=read();
          if (p[i]==1) now++;
       }
     for (int i=1;i<=n;i++) jiangli[i]=read();
     for (int i=1;i<=mm;i++) atk[i]=read(),insert(atk[i]);
     if (now==n) {
        solve3();
        continue;
     }
     solve1();
     if (!flag) {
        cout<<-1<<endl;
        continue;
     }
     //cout<<"hhh"<<endl;
     //for (int i=1;i<=n;i++) cout<<a[i]<<endl;
     ll ans=solve();
     if (!flag) {
        cout<<-1<<endl;
        continue;
     }
     cout<<ans<<endl;
  }
  return 0;
}

猜你喜欢

转载自blog.csdn.net/y752742355/article/details/81191769
今日推荐