zoukankan      html  css  js  c++  java
  • 题解「Luogu4774 [NOI2018]屠龙勇士」

    转载注明来源:https://www.cnblogs.com/syc233/p/13654606.html


    首先发现对每条龙使用的剑是固定的,于是可以用multiset预处理出对每条龙使用的剑 (b_i)

    然后发现题其实是要求一堆形如这个的式子:

    [a_i-x cdot b_i+y cdot p_i=0 (x,y in ) ]

    明显这是一个二元一次不定方程,把它化成标准形式:

    [x cdot b_i+y cdot p_i=a_i (x,y in ) ]

    用exgcd求出这个方程的一组通解 (x_0,y_0) 。若无解,则直接输出 (-1) ,否则有(为了方便,以下均使用 ((i,j)) 表示 ({ m{gcd}}(i,j)) ):

    [x=frac{a_i}{(b_i,p_i)}x_0+k cdot frac{p_i}{(b_i,p_i)} iff x equiv x_0 ({ m{mod}} frac{p_i}{(b_i,p_i)}) ]

    对每一个二元一次不定方程进行上述操作,令 (A_i=x_0,B_i=frac{p_i}{(b_i,p_i)}) ,则需要求解如下同余方程组:

    [egin{cases} x equiv A_1 ({ m{mod}} B_1)\ x equiv A_2 ({ m{mod}} B_2)\ cdots \ x equiv A_n ({ m{mod}} B_n)\ end{cases} ]

    用exCRT合并即可。

    特判 (p_i=1) ,让所有龙的血量非正即可。


    ( ext{Code}:)

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    #include <set>
    #define maxn 100005
    #define Rint register int
    #define INF 0x3f3f3f3f
    using namespace std;
    typedef long long lxl;
    
    template <typename T>
    inline void read(T &x)
    {
    	x=0;T f=1;char ch=getchar();
    	while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
    	x*=f;
    }
    
    inline lxl fti(lxl a,lxl b,lxl mod)
    {
    	lxl res=0;
    	while(b>0)
    	{
    		if(b&1) (res+=a)%=mod;
    		(a+=a)%=mod;
    		b>>=1;
    	}
    	return res;
    }
    
    inline lxl exgcd(lxl a,lxl b,lxl &x,lxl &y)
    {
    	if(!b) {x=1,y=0;return a;}
    	lxl res=exgcd(b,a%b,x,y);
    	lxl z=x;x=y;y=z-(a/b)*y;
    	return res;
    }
    
    int n,m;
    lxl a[maxn],p[maxn],b[maxn],aw[maxn];
    multiset<lxl> s;
    #define IT multiset<lxl>::iterator
    
    lxl A[maxn],B[maxn];
    
    int main()
    {
    	// freopen("P4774.in","r",stdin);
    	int T;read(T);
    	while(T--)
    	{
    		read(n),read(m);
    		s.clear();
    		lxl mx=0;
    		for(int i=1;i<=n;++i) read(a[i]);
    		for(int i=1;i<=n;++i) read(p[i]),mx=max(mx,p[i]);
    		for(int i=1;i<=n;++i) read(aw[i]);
    		for(int i=1;i<=m;++i)
    		{
    			lxl w;read(w);
    			s.insert(w);
    		}
    		bool flag=true;
    		for(int i=1;i<=n;++i)
    		{
    			IT it=s.upper_bound(a[i]);
    			if(it!=s.begin()) --it;
    			b[i]=*it;
    			s.erase(it);
    			s.insert(aw[i]);
    			lxl x,y,d=exgcd(b[i],p[i],x,y);
    			if(a[i]%d) {flag=false;break;}
    			a[i]/=d,p[i]/=d;
    			x=fti(x,a[i],p[i]);
    			B[i]=p[i];
    			A[i]=(x%B[i]+B[i])%B[i]; 
    		}
    		if(!flag) {puts("-1");continue;}
    		if(mx==1)
    		{
    			lxl ans=0;
    			for(int i=1;i<=n;++i)
    				ans=max(ans,(a[i]+b[i]-1)/b[i]);
    			printf("%lld
    ", ans);
    			continue;
    		}
    		lxl M=B[1],ans=A[1];
    		for(int i=2;i<=n;++i)
    		{
    			lxl b1=M,b2=B[i],c=(A[i]-ans%b2+b2)%b2,x,y;
    			lxl d=exgcd(b1,b2,x,y);
    			if(c%d) {flag=false;break;}
    			b2/=d,c/=d;
    			x=fti(x,c,b2);
    			ans+=M*x;
    			M*=B[i]/d;
    			(ans+=M)%=M;
    		}
    		if(!flag) {puts("-1");continue;}
    		printf("%lld
    ",(ans+M)%M);
    	}
    	return 0;
    }
    

    参考资料:

    扩展欧几里得定理

    CRT 中国剩余定理

    其实是忘完了去复习了一下

  • 相关阅读:
    C#实现office文档转换为PDF或xps的一些方法
    Asp.Net性能优化.
    我们该如何在网上寻找资源!!!!
    用谷歌浏览器来当手机模拟器
    js 文档高度
    文件的ContentType类型网页设计,HTML/CSS
    javascript 获取滚动条高度+常用js页面宽度与高度[转]
    学习MVC
    windows自带性能监控器
    C#语言规范之小结
  • 原文地址:https://www.cnblogs.com/syc233/p/13654606.html
Copyright © 2011-2022 走看看