• 「CF338D」GCD Table


    「CF338D」GCD Table

    problem

    题意

    有一张(n imes m)的表,其中第(i)行第(j)列的元素是(gcd(i,j))

    给定一个长度为(k)的序列(a),询问在表中是否存在一对((x,y))使得(forall iin[1,k],a_i=gcd(x,y+i-1))

    Solutions

    以下引自@siyuan的题解


    Solution

    由于我们要保证 (gcd(x,y)=a_i),显然 (lcm(a_1,a_2,…,a_k)∣x)

    我们尝试证明:如果有解,那么(x)的值可以为(lcm(a_1,a_2,…,a_k))

    如果有解,且(x=K imes lcm(a1,a2,…,ak)),那么意味着(gcd(K,y)=0),这样一来我们给(y)平白无故地增加了限制。因此如果 (x=K imes lcm(a_1,a_2,…,a_k))时有解,那么在 (x=lcm(a_1,a_2,…,a_k))时一定也有解。

    在确定了(x)的值之后,还需要满足(a_i∣y+i−1),即满足下列同余方程:

    [egin{cases}y=0pmod {a_1}\y=-1pmod {a_2}\vdots\y=-k+1pmod {a_k}end{cases} ]

    这个方程显然可以通过扩展中国剩余定理来求解(y)即可。

    但是我们发现,求出(y)之后的解 ((x,y))

    不一定就是合法的,这是为什么呢?

    其实我们通过这样的思路,推导出解只满足必要性,而不满足充分性。因此我们还需要将((x,y))代入 (gcd(x,y+i−1)=ai(1≤i≤k))验证。

    时间复杂度:(O(klog a_i))


    Code

    没想清楚细节WA了好几发

    #include <cstdio>
    #include <cstdlib>
    #include <cmath>
    #include <algorithm>
    #include <cstring>
    #include <iostream>
    using namespace std;
    typedef long long ll;
    
    template <typename T>void read(T &t)
    {
    	t=0;int f=0;char c=getchar();
    	while(!isdigit(c)){f|=c=='-';c=getchar();}
    	while(isdigit(c)){t=t*10+c-'0';c=getchar();}
    	if(f)t=-t;
    }
    
    const int maxk=10000+5;
    ll n,m;
    int K;
    ll X,Y;
    ll a[maxk],r[maxk];
    
    ll gcd(ll a,ll b)
    {
    	return b?gcd(b,a%b):a;
    }
    
    ll exgcd(ll a,ll b,ll &x,ll &y)
    {
    	if(!b)
    	{
    		x=1,y=0;
    		return a;
    	}
    	ll xx,yy,re=exgcd(b,a%b,xx,yy);
    	x=yy;
    	y=xx-a/b*yy;
    	return re;
    }
    
    ll excrt()
    {
    	ll M=a[1],R=r[1];
    	for(register int i=2;i<=K;++i)
    	{
    		ll k1,k2,g=exgcd(M,a[i],k1,k2);
    		if((r[i]-R)%g)return -1;
    		k1=(r[i]-R)/g*k1%a[i];
    		R+=k1*M;
    		M=M/g*a[i];
    		R%=M;
    	}
    	return (R-1+M)%M+1;
    }
    
    int main()
    {
    	read(n),read(m),read(K);
    	read(a[1]),r[1]=0,X=a[1];
    	for(register int i=2;i<=K;++i)
    	{
    		read(a[i]),r[i]=1-i;
    		ll g=gcd(X,a[i]);
    		X=X/g*a[i];
    	}
    	Y=excrt();
    	if(X>n || Y+K-1>m || Y<1)
    	{
    		printf("NO");
    		return 0;
    	}
    	for(register int i=1;i<=K;++i)
    		if(gcd(X,Y+i-1)!=a[i])
    		{
    			printf("NO");
    			return 0;
    		}
    	printf("YES");
    	return 0;
    }
    
  • 相关阅读:
    Silverlight 4 新特性之NotificationWindow
    如何理解JavaScript原型
    惹恼程序员的十件事
    浅谈HTTP中Get与Post的区别
    asp中Access与Sql Server数据库区别总结
    SQL208语句
    jQuery源码分析
    3. 在 as 和 强制类型转换之间,优先使用 as 操作符。
    揭秘10项必学的.NET技术
    如何设置远程访问SQL Server2005
  • 原文地址:https://www.cnblogs.com/lizbaka/p/10631988.html
Copyright © 2020-2023  润新知