CF338D GCD Table-题解(excrt)

CF338D GCD Table

个人评价:还好

算法

扩展CRT

题面

给了一张n×m的矩阵,第i行j列的权值是gcd(i,j),现在有一个长度为k的序列A,问是否存在(i,j)使得gcd(i,j+l1)=al(1lk)

问题分析

我们将对应行设为x,对应列设为y,那么就有如下同余方程组

x(y+l1)(moda[l])

但还是感觉不行,找一下y和a的规律,好像没有办法搞

我们对于x和y分别分析:

1.对于x来说:

序列a中的每一个元素都是x的因数,显然有x=lcm(a[i])×k,其中k不一定是一个质数

2.对于y来说:

我们将同余方程拆开,那么可以得到如下方程组

y0(moda[1]),y+11(moda[2])

稍微结合一下下就是

{y0(moda[1])y1(moda[2])y2(moda[3])y3(moda[4])y(k1)(moda[k])

然后我们就可以y给解出来,同理,只要判断一下下x是否有解就行了

代码实现

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const ll M=1e4+10;
ll n,m,k,a[M];
struct equations{
	ll p,r;
}b[M];
ll qmul(ll x,ll y,ll mod){ 
    return (x*y-(ll)((long double)x/mod*y)*mod+mod)%mod;
}
ll gcd(ll x,ll y){
	if(!y)return x;
	return gcd(y,x%y);
}
ll exgcd(ll a,ll b,ll &x,ll &y){
	if(b==0){
		x=1,y=0;
		return a;
	}
	ll r=exgcd(b,a%b,x,y),tmp;
	tmp=x;x=y;y=tmp-(a/b)*y;
	return r;
}
ll inv(ll a,ll b){
	ll x,y;
	x=0,y=0;
	exgcd(a,b,x,y);
	while(x<0)x+=b;
	return x;
}
void init(){
	 for(ll i=1;i<=k;i++){
	 	b[i].p=a[i];
	 	b[i].r=1-i;
	 	b[i].r=(b[i].r+b[i].p)%b[i].p;
	 }
}
ll solve(){//这个excrt卡了我半年……
	int fg=1;
	for(ll i=2;i<=k;i++){
		ll mul1=b[i-1].p,mul2=b[i].p;
		ll r1=b[i-1].r,r2=b[i].r;
		ll GCD=gcd(mul1,mul2);
		if((r2-r1)%GCD!=0){
			printf("NO");
			exit(0);
		}
		b[i].p=(mul1*mul2)/GCD;
		b[i].r=qmul(qmul(inv(mul1/GCD,mul2/GCD),(r2-r1)/GCD,mul2/GCD),mul1,b[i].p)+r1;
        b[i].r=(b[i].r%b[i].p+b[i].p)%b[i].p;
	}
	if(fg==0||k==1)return -1;
	if(b[k].r==0)return b[k].p;
	return b[k].r;
}
int main(){
	ll lcm=1;
	scanf("%lld%lld%lld",&n,&m,&k);
	for(ll i=1;i<=k;i++){	
		scanf("%lld",&a[i]);
		lcm=lcm/gcd(lcm,a[i])*a[i];
		if(lcm>n){//注意越界判断
			printf("NO");
			return 0;
		}
	}
	init();
	ll y=solve();
	if(y+k-1>m){//同样是越界判断
		printf("NO");
		return 0;
	}
	for(int i=1;i<=k;i++){
		if(gcd(lcm,y+i-1)!=a[i]){//对于x的分析可得
			printf("NO");
			return 0;
		}
	}
	printf("YES");
	return 0;
}

总结

我们在一些数论的题目当中试着将一些公式带数据yy套进去,看一下能不能套对,反正数论的基础公式就那几个

posted @   6penny  阅读(31)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
点击右上角即可分享
微信分享提示