• LOJ2721 [NOI2018] 屠龙勇士 【扩展中国剩余定理】


    好久没写了,写一篇凑个数。

    题目分析:

    这题不难想,讲一下中国剩余定理怎么扩展。

    考虑$$left{egin{matrix}x equiv apmod{b}\ x equiv cpmod{d}end{matrix} ight.$$

    不难发现需要满足$gcd(b,d)|(c-a)$才有解。

    结合后的模数一定是$lcm(b,d)$。然后扩展gcd合并就行了。

    中间过程会超过$10^18$,需要快速乘。

    代码:

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 
     4 const int maxn = 120000;
     5 
     6 int n,m;
     7 long long a[maxn],p[maxn],LP[maxn],d[maxn];
     8 
     9 multiset<long long,greater<long long> > s;
    10 
    11 long long cut[maxn],minn;
    12 long long st[maxn],f[maxn];
    13 
    14 void init(){
    15     s.clear();memset(st,0,sizeof(st)); memset(f,0,sizeof(f));
    16     for(int i=1;i<=m;i++) s.insert(d[i]);
    17     for(int i=1;i<=n;i++){
    18     set<long long>::iterator it = s.lower_bound(a[i]);
    19     if(it == s.end())it--;    cut[i] = (*it);
    20     s.erase(it); s.insert(LP[i]);
    21     }
    22     minn = 0;
    23     for(int i=1;i<=n;i++) minn = max(minn,(long long)ceil((double)a[i]/cut[i]));
    24 }
    25 
    26 long long exgcd(long long alpha,long long beta,long long &x,long long &y){
    27     if(beta == 0){x = 1; y = 0; return alpha;}
    28     else{
    29     long long res = exgcd(beta,alpha%beta,y,x);
    30     y-=x*(alpha/beta);
    31     return res;
    32     }
    33 }
    34 
    35 void read(){
    36     scanf("%d%d",&n,&m);
    37     for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
    38     for(int i=1;i<=n;i++) scanf("%lld",&p[i]);
    39     for(int i=1;i<=n;i++) scanf("%lld",&LP[i]);
    40     for(int i=1;i<=m;i++) scanf("%lld",&d[i]);
    41 }
    42 
    43 long long multi(long long alpha,long long beta,long long mod){
    44     long long dt,bit = 1,ans = 0;
    45     alpha %= mod; beta %= mod;
    46     alpha += mod; beta += mod;
    47     alpha %= mod; beta %= mod;
    48     dt = alpha;
    49     while(bit <= beta){
    50     if(bit & beta){ans += dt; if(ans >= mod) ans -= mod;}
    51     bit<<=1;dt = (dt+dt); if(dt >= mod) dt -= mod;
    52     }
    53     return ans;
    54 }
    55 
    56 int cntt = 0;
    57 void work(){
    58     for(int i=1;i<=n;i++){
    59     long long hd = exgcd(cut[i],p[i],st[i],f[i]);
    60     if(a[i] % hd != 0){puts("-1");return;}
    61     f[i] = p[i]/hd; st[i] %= f[i]; if(st[i] < 0) st[i] += f[i];
    62     st[i] = multi(st[i],a[i]/hd,f[i]); st[i] %= f[i];
    63     }
    64     for(int i=2;i<=n;i++){
    65     long long im = exgcd(f[i],f[i-1],f[0],f[0]);
    66     if((st[i]-st[i-1])%im){
    67         puts("-1");return;
    68     }
    69     long long um = f[i]/im*f[i-1];
    70     long long tf=0; exgcd(f[i-1],f[i],tf,f[0]);
    71     tf =multi(tf,(st[i]-st[i-1])/im,um);
    72     tf += (-tf/f[i])*f[i]; tf += f[i];
    73     tf = (st[i-1]+multi(tf,f[i-1],um))%um;
    74     if(tf < 0) tf += um;
    75     f[i] = um; st[i] = tf;
    76     }
    77     if(st[n] < minn){
    78     st[n] += (minn-st[n])/f[n]*f[n];
    79     }
    80     printf("%lld
    ",st[n]);
    81     //fast multi
    82 }
    83 
    84 int main(){
    85     int Tmp; scanf("%d",&Tmp);
    86     while(Tmp--){
    87     cntt++;
    88     read();
    89     init();
    90     work();
    91     }
    92     return 0;
    93 }
  • 相关阅读:
    spring(二) AOP之AspectJ框架的使用
    spring(一) IOC讲解
    struts2(六) 文件上传和下载
    导入Excel后绑定GridView实例
    类型“GridView”的控件必须放在具有 runat=server 的窗体标记内?
    只能在执行 Render() 的过程中调用 RegisterForEventValidation
    C# 连接SQL Server数据库的几种方式--server+data source等方式
    C#未将对象引用设置到对象的实例
    代码保存好
    在选定的数据源上未找到名为“TitleSub”的字段或属
  • 原文地址:https://www.cnblogs.com/Menhera/p/9347222.html
Copyright © 2020-2023  润新知