• P1516 青蛙的约会和P2421 [NOI2002]荒岛野人


    洛谷 P1516 青蛙的约会
    算是手推了一次数论题,以前做的都是看题解,虽然这题很水而且还交了5次才过。。。

    求解方程(x+amequiv y+an pmod l)中,(a)的最小整数解
    (0<x eq yleq 2cdot 10^9,0<n,mleq 2cdot 10^9,0<lleq 2.1cdot 10^9)


    做一下变形:

    [x-yequiv a(n-m) pmod l ]

    (w=x-y,r=n-m),则

    [arequiv w pmod l ]

    此时,设(gcd(l,r)=gcd),那么可以分两种情况

    如果(w)(gcd)的倍数,则原式可以写为:

    [ar'gcdequiv w'gcd pmod{l'gcd} ]

    根据同余式的性质,可以将(gcd)化简掉,具体证明在这里

    [ar'equiv w'pmod l' ]

    此时,(gcd(r',l')=1),那么可以求出(r' mod l')的逆元
    那么(w'r'^{-1}mod l')即为答案
    具体操作就是用 exgcd,求出一个(qr+pl=gcd(r,l)),然后可以表示为(qr'gcd+pl'gcd=gcd)
    (gcd)被约掉,就是(qr'+pl'=1),则(q)即为(r'mod l')的逆元

    还有一种情况(w)不是(gcd)的倍数,显然无解

    再就是注意(w,r)会不会出现负数,如果有负数在取模的时候可能会出现一些玄学情况,要现在(mod l)下把他们变成正的

    #include<cstdio>
    #include<algorithm>
    #include<iostream>
    #include<cmath>
    #include<iomanip>
    #include<cstring>
    #define reg register
    #define EN std::puts("")
    #define LL long long
    inline LL read(){
    	LL x=0,y=1;
    	char c=std::getchar();
    	while(c<'0'||c>'9'){if(c=='-') y=0;c=std::getchar();}
    	while(c>='0'&&c<='9'){x=x*10+(c^48);c=std::getchar();}
    	return y?x:-x;
    }
    LL exgcd(LL &x,LL &y,LL a,LL b){
    	if(!b) return x=1,y=0,a;
    	LL gcd=exgcd(x,y,b,a%b);
    	int xx=x;x=y;
    	y=xx-a/b*y;
    	return gcd;
    }
    int main(){
    	LL n,m,x,y,l;
    	x=read();y=read();m=read();n=read();l=read();
    	if(m==n) return std::puts("Impossible"),0;
    	LL r=n-m,w=x-y;
    	if(r<0) r=(r+((-r/l)+1)*l)%l;
    	if(w<0) w=(w+((-w/l)+1)*l)%l;
    	LL a,b;
    	int gcd=exgcd(a,b,r,l);
    	if(w%gcd) return std::puts("Impossible"),0;
    	l/=gcd;w/=gcd;
    	std::printf("%lld",(w*a%l+l)%l);
    	return 0;
    }
    

     

    洛谷 P2421 [NOI2002]荒岛野人LOJ上也有
    这题和上面那个几乎一样,代码复制过去改一改加个主函数就行

    克里特岛以野人群居而著称。岛上有排列成环行的(M)个山洞。这些山洞顺时针编号为 (1,2,dots,M)
    岛上住着(n)个野人,一开始依次住在山洞 (C_1,C_2,dots,C_n)中。以后每年,第 (i) 个野人会沿顺时针向前走 (P_i)个洞住下来。
    每个野人(i)有一个寿命值 (L_i),即生存的年数。

    奇怪的是,虽然野人有很多,但没有任何两个野人在有生之年处在同一个山洞中,使得小岛一直保持和平与宁静,这让科学家们很是惊奇。他们想知道,至少有多少个山洞,才能维持岛上的和平呢?数据保证有解,(M) 的值不大于(10^6)

    这是真正的数据范围,洛谷上标的很乱:(0<C_i,P_ileq 100,1leq Nleq 15,0leq L_ileq 10^6)


    把题意描述成数学语言,就是求一个最小的(M),使得对于任意的(i eq j,c_i+kp_iequiv c_j+kp_j pmod M)无解,或解大于(min(L_i,L_j))
    然后这个式子就和上面那个题一模一样了,就是记得判断解的大小就行

    一开始想二分处理,然而发现并不满足可二分性,但保证(Mleq 10^6),很小,而且又保证有解,所以可以从(max c_i)开始枚举(M),枚举到成立就行了
    复杂度(O(Mn^2log C_i)),超过(10^9)了,而且这还是02年的题,那时候恐怕测评机比现在也慢
    不过肯定是跑不满,也不太可能会有什么毒瘤数据,估计是没有更优做法了

    #include<cstdio>
    #include<algorithm>
    #include<iostream>
    #include<cmath>
    #include<iomanip>
    #include<cstring>
    #define reg register
    #define EN std::puts("")
    #define LL long long
    inline int read(){
    	register int x=0;register int y=1;
    	register char c=std::getchar();
    	while(c<'0'||c>'9'){if(c=='-') y=0;c=std::getchar();}
    	while(c>='0'&&c<='9'){x=x*10+(c^48);c=std::getchar();}
    	return y?x:-x;
    }
    int exgcd(int &x,int &y,int a,int b){
    	if(!b) return x=1,y=0,a;
    	LL gcd=exgcd(x,y,b,a%b);
    	int xx=x;x=y;
    	y=xx-a/b*y;
    	return gcd;
    }
    inline int check(int m,int n,int x,int y,int l,int min){//calc am+x = an+y mod l 
    	if(m==n) return 0;
    	LL r=n-m,w=x-y;
    	if(r<0) r=(r+((-r/l)+1)*l)%l;
    	if(w<0) w=(w+((-w/l)+1)*l)%l;
    	int a,b;
    	int gcd=exgcd(a,b,r,l);
    	if(w%gcd) return 0;
    	w/=gcd;l/=gcd;
    	if((w*a%l+l)%l>min) return 0;
    	return 1;
    }
    int c[19],p[19],l[19];
    int main(){
    	int n=read(),maxc=0;
    	for(reg int i=1;i<=n;i++) c[i]=read(),p[i]=read(),l[i]=read(),maxc=std::max(maxc,c[i]);
    	for(reg int m=maxc;;m++){
    		for(reg int i=1;i<=n;i++)
    			for(reg int j=i+1;j<=n;j++)
    				if(check(p[i],p[j],c[i],c[j],m,std::min(l[i],l[j]))) goto FAIL;
    		return std::printf("%d",m),0;
    		FAIL:;
    	}
    	return 0;
    }
    
  • 相关阅读:
    Bootstrap3.0学习第八轮(工具Class)
    dependencies与dependencyManagement的区别
    灵活控制 Hibernate 的日志或 SQL 输出,以便于诊断
    Linux平台安装MongoDB
    ubuntu 该软件包现在的状态极为不妥 error
    oracle vm突然黑屏了
    Oracle VM VirtualBox各种显示模式切换 热键
    where后一个条件和多个条件的查询速度
    String特殊值的判断方式
    将中文标点符号替换成英文标点符号
  • 原文地址:https://www.cnblogs.com/suxxsfe/p/12610744.html
Copyright © 2020-2023  润新知