【题解】[NOI2018] 屠龙勇士

solution:

毒瘤题。

注意我们只关注同余方程有解即可。

根据题意得到 a i + p i ∗ y = A T K ∗ x i a_i+p_i*y=ATK*x_i ai+piy=ATKxi

化简得到 A T K ∗ x i ≡ a i ( m o d p i ) ATK*x_i\equiv a_i\pmod {p_i} ATKxiai(modpi) ,这个式子等价于 A T K ≡ b i ( m o d p i ( p i , x i ) ) ATK\equiv b_i\pmod {\frac{p_i}{(p_i,x_i)}} ATKbi(mod(pi,xi)pi) ,其中 b i b_i bi 是满足 b i ∗ x i ≡ a i ( m o d p i ) b_i*x_i\equiv a_i\pmod {p_i} bixiai(modpi) 的最小非负整数解。

把上面的式子扔进 excrt 即可。注意 p i = 1 p_i=1 pi=1 特判。

时间复杂度 O(Tn(loglcm+logn)) 。

#include <bits/stdc++.h> #define INF 0x3f3f3f3f #define PII pair<int,int> #define PIII pair<int,PII> #define ll long long #define INF 0x3f3f3f3f using namespace std; const int mx=1e5+5; int n,q; ll a[mx],m[mx],t[mx],p[mx],ad[mx]; multiset<ll> s; ll gcd(ll x,ll y) { return y==0?x:gcd(y,x%y); } ll fmul(ll x,ll y,ll z) { x%=z,y%=z; if(y<0) x=-x,y=-y; ll sum(0); for(;y;y>>=1) { if(y&1) sum=(sum+x)%z; x=(x+x)%z; } return sum; } ll lcm(ll x,ll y) { if(x==0||y==0) return x^y; return x/gcd(x,y)*y; } void exgcd(ll &x,ll &y,ll a,ll b,ll &d) { if(b==0) { x=1,y=0,d=a; } else { exgcd(y,x,b,a%b,d); y-=x*(a/b); } } bool excrt() { for(int i=1;i<=n;i++) { if(a[i]>=m[i]) return 1; } for(int i=2;i<=n;i++) { ll tmp=((a[i]-a[1])%m[i]+m[i])%m[i]; ll k1,k2,d; exgcd(k1,k2,m[1],m[i],d); if(tmp%d) return 1; k1=(fmul(k1,tmp/d,m[i]/d)+(m[i]/d))%(m[i]/d); ll M=m[1]/d*m[i]; a[1]=(a[1]+fmul(m[1],k1,M))%M; m[1]=M; } return 0; } void solve() { ll tmp(0); for(int i=1;i<=n;i++) { auto it=s.upper_bound(t[i]); if(it!=s.begin()) it--; ll x=*it; s.erase(it); s.insert(ad[i]); if(t[i]%gcd(x,p[i])) { printf("-1\n"); return; } //求解 x*k1=a (mod p[i]) 的最小非负整数 //k1 周期为 p[i]/gcd(p[i],x) ll k1,k2,d; exgcd(k1,k2,x,p[i],d); ll mo=p[i]/d; k1=(fmul(k1,t[i]/d,mo)+mo)%mo; //等价转化为 ATK=k1 (mod p[i]/d) m[i]=mo; a[i]=k1; if(m[i]==1) tmp=max(tmp,(t[i]+x-1)/x); } if(excrt()) { printf("-1\n"); return; } a[1]=max(a[1],tmp); printf("%lld\n",a[1]); return; } signed main() { int T; scanf("%d",&T); while(T--) { scanf("%d%d",&n,&q); s.clear(); for(int i=1;i<=n;i++) { scanf("%lld",&t[i]); } for(int i=1;i<=n;i++) { scanf("%lld",&p[i]); } for(int i=1;i<=n;i++) { scanf("%lld",&ad[i]); } for(int i=1;i<=q;i++) { ll x; scanf("%lld",&x); s.insert(x); } solve(); } }

__EOF__

本文作者仰望星空的蚂蚁
本文链接https://www.cnblogs.com/cqbzly/p/17530264.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   仰望星空的蚂蚁  阅读(7)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· DeepSeek 开源周回顾「GitHub 热点速览」
点击右上角即可分享
微信分享提示