• NOI2018 屠龙勇士


    题目链接:
    https://loj.ac/problem/2721
    https://www.luogu.org/problemnew/show/P4774

    显然可以发现每次使用的剑是可以用平衡树来维护,假如杀第\(i\)头龙使用攻击为\(b[i]\)的剑。
    龙既然要恢复到0的血量,说明:
    \(b[i]*x>=a[i]\)
    \(b[i]*x \equiv a[i](mod \; p[i])\)
    对于第二个条件我们解一个同余方程组,用扩展中国剩余定理合并为一个同余方程,再根据条件一找到最小的x。注意中间运算会爆\(long long\),要用快速乘。

    关于解同余方程:
    有解的充要条件是\(gcd(b[i],p[i]) | a[i]\)
    我们可以先将\(b,a,p\)同时除以\(gcd(b,a,p)\)再判断除后的\(gcd(b,p)==1\),不满足则无解。
    再通过求\(b\)在模\(p\)意义下的逆元化为\(x \equiv ab^{-1}( mod \; p)\)的形式再用CRT合并。
    (存在逆元的充要条件是\(gcd(b,p)==1\))。

    看代码请移步,蒟蒻写的太烂,以后会更新好一点QWQ。



























    #include<bits/stdc++.h>
    using namespace std;
    const int N=100010;
    typedef  long long ll;
    void exgcd(ll a,ll b,ll& d,ll& x,ll& y){
        if(!b){ d=a; x=1; y=0;}
        else{ exgcd(b,a%b,d,y,x); y-=x*(a/b); }
    }
    ll inverse(ll a,ll n){
        ll d,x,y;
        exgcd(a,n,d,x,y);
        return d==1?(x+n)%n:-1;
    }
    struct node{
        node*ch[2];
        int r,cnt,s;
        ll v;
        int cmp(ll x){
            if(v==x) return -1;
            else return v<x;
        }
        void maintain(){s=ch[0]->s+ch[1]->s+cnt;}
    };
    void rotate(node*&o,int d){
        node*k=o->ch[d^1];
        o->ch[d^1]=k->ch[d];
        k->ch[d]=o;
        o->maintain();
        k->maintain();
        o=k;
    }
    node*root,*null=new node();
    void insert(node*&o,ll x){
        if(o==null){
            o=new node();
            o->v=x;
            o->r=rand();
            o->ch[0]=o->ch[1]=null;
            o->cnt=1;
        }
        else{
            int d=o->cmp(x);
            if(d==-1){o->cnt++,o->s++;return;}
            insert(o->ch[d],x);
            if(o->ch[d]->r>o->r) rotate(o,d^1);
        }
        o->maintain();
    }
    void remove(node*&o,ll x){
        int d=o->cmp(x);
        if(d==-1){
            if(o->cnt>1) {o->cnt--,o->s--;return;}
            node*u=o;
            if(o->ch[0]!=null&&o->ch[1]!=null) {
                d=o->ch[0]->r>o->ch[1]->r;
                rotate(o,d),remove(o->ch[d],x);
            }
            else{
                if(o->ch[0]!=null) o=o->ch[0];
                else o=o->ch[1];
                delete u;
            }
        }else remove(o->ch[d],x);
        if(o!=null) o->maintain();
    }
    ll kth(node*o,int k){
        if(o==null) return 0;
        int s=o->ch[0]->s;
        if(k>s&&k<=s+o->cnt) return o->v;
        else if(k<=s) return kth(o->ch[0],k);
        else return kth(o->ch[1],k-s-o->cnt);
    }
    int rank(node*o,ll x){
        ll ans=0;
        while(o->v!=x){
            if(o->v<x) ans+=o->ch[0]->s+o->cnt,o=o->ch[1];
            else o=o->ch[0];
        }
        return ans+o->ch[0]->s+1;
    }
    ll getpre(node*o,ll x){
        ll ans;
        bool k=1;
        while(o!=null){
            if(o->v<=x) ans=o->v,o=o->ch[1],k=0;
            else o=o->ch[0];
        }
        if(k) return 0;
        return ans;
    }
    ll getnxt(node*o,ll x){
        ll ans;
        while(o!=null){
            if(o->v>x) ans=o->v,o=o->ch[0];
            else o=o->ch[1];
        }
        return ans;
    }
    ll ksc(ll a,ll n,ll p){
        a%=p;n%=p;
        ll ans=0;
        for(;n;n>>=1,a=(a+a)%p){
            if(n&1) ans=(ans+a)%p;
        }
        return ans;
    }
    void clear(node* o){
        if(o!=null){
            clear(o->ch[0]);
            clear(o->ch[1]);
            delete o;
        }
    }
    ll get(ll a){
        int b=getpre(root,a);
        if(b==0) b=getnxt(root,a);
        return b;
    }
    ll gcd (ll a,ll b){
        return b?gcd(b,a%b):a;
    }
    ll lcm(ll a,ll b){
        return (a/gcd(a,b))*b;
    }
    ll swd[N],_swd[N],a[N],p[N],b[N];
    int main(){
    //	freopen("dragon3.in","r",stdin);
        null->s=0;
        null->v=0;
        root=null;
        int n,m,t=1;
        scanf("%d",&t);
        while(t--){
            scanf("%d%d",&n,&m);
            root=null;
            ll mx=-2333333333333;
            for(int i=1;i<=n;i++) { cin>>a[i];}
            for(int i=1;i<=n;i++) cin>>p[i];
            for(int i=1;i<=n;i++) cin>>_swd[i];
            for(int i=1;i<=m;i++){
                cin>>swd[i];
                insert(root,swd[i]);
            }
            ll nowb=get(a[1]);
            ll lastp=p[1];
            remove(root,nowb);
            ll agcd=gcd(gcd(nowb,lastp),a[1]);
            nowb/=agcd;
            a[1]/=agcd;
            lastp/=agcd;
            b[1]=nowb;
            if(gcd(nowb,lastp)>1){
                puts("-1");
                clear(root);
                continue;
            }
            nowb=inverse(nowb,lastp);
            ll nowa=ksc(a[1],nowb,lastp);
            insert(root,_swd[1]);
            bool ok=1;
            for(int i=2;i<=n;i++){
                ll now2b=get(a[i]);
                remove(root,now2b);
                ll agcd=gcd(gcd(now2b,p[i]),a[i]);
                now2b/=agcd;
                a[i]/=agcd;
                p[i]/=agcd;
                b[i]=now2b;
                if(gcd(now2b,p[i])>1){
                    puts("-1");
                    clear(root);
                    ok=0;
                    break;
                }
                now2b=inverse(now2b,p[i]);
                ll now2a=ksc(a[i],now2b,p[i]);
                ll d,y11,y22;
                exgcd(lastp,-p[i],d,y11,y22);		
                ll kk=now2a-nowa;	
                if(kk%d!=0){
                    puts("-1");
                    clear(root);
                    ok=0;
                    break;
                }
                ll k=lastp;
                lastp=lcm(lastp,p[i]);
                nowa=((ksc(ksc((kk/d),y11,lastp),k,lastp)
                +nowa)%lastp+lastp)%lastp;
                insert(root,_swd[i]);
            }
            if(!ok) continue;
            for(int i=1;i<=n;i++){
                ll k=a[i]-b[i]*nowa;
                if(k>0){
                    ll kk=b[i]*lastp;
                    if(k%kk==0) nowa+=(k/kk);
                    else nowa+=k/kk+1;
                }
            }
            cout<<nowa<<endl;
        }
        return 0;
    }
    
        
    
  • 相关阅读:
    clearfix 清除浮动的问题
    python第四十五课——继承性之多继承
    Linux基础第六课——grep|awk|sort|uniq
    Linux基础第五课——用户管理
    Linux基础第四课——文件操作
    Linux第三课——目录操作
    Linux基础第二课——系统架构
    Linux基础第一课——基础知识了解
    01 http协议概念及工作流程
    18- php Redis扩展编译
  • 原文地址:https://www.cnblogs.com/lsq647vsejgfb/p/9348496.html
Copyright © 2020-2023  润新知