CF338D GCD Table-题解(excrt)
CF338D GCD Table
个人评价:还好
算法
扩展CRT
题面
给了一张
问题分析
我们将对应行设为x,对应列设为y,那么就有如下同余方程组
但还是感觉不行,找一下y和a的规律,好像没有办法搞
我们对于x和y分别分析:
1.对于x来说:
序列a中的每一个元素都是x的因数,显然有
2.对于y来说:
我们将同余方程拆开,那么可以得到如下方程组
稍微结合一下下就是
然后我们就可以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套进去,看一下能不能套对,反正数论的基础公式就那几个
分类:
题解
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通