CF338D GCD Table
题目描述
给你 。
你有一个长度为 的数列 。
询问是否存在 ,,满足 。
若存在,输出 YES
,否则,输出 NO
。
对于 的数据,保证 。
解题思路
前置知识:exCRT
。
根据题意显然可以列出:
我们知道 ,显然有:,
即:
即:
和
整理出:
显然 之间不一定互质,所以我们直接使用拓展中国剩余定理求解即可,这样我们就可以求出一个合法的 。
显然 可以整除所有的 ,那么满足条件的最小的 显然是 。
求出 以后验证是否在范围内即可。
时间复杂度 。
CODE
#include <bits/stdc++.h>
using namespace std;
#define int long long
int read()
{
int f = 1, x = 0;
char c = getchar();
while(c < '0' || c > '9'){if(c == '-') f = -1; c = getchar();}
while(c >= '0' && c <= '9'){x = x * 10 + c - '0'; c = getchar();}
return f * x;
}
const int maxn = 100010;
int n, p;
int a, b;
int Lcm = 1;
int ai[maxn], bi[maxn];
int js(int x, int mod)
{
if(x < mod) return x;
return x % mod + mod;
}
int gcd(int a, int b)
{
if(!b) return a;
return gcd(b, a % b);
}
int lcm(int a, int b)
{
return a / gcd(a, b) * b;
}
int mul(int a, int b, int mod)
{
if(b < 0) a = -a, b = -b;
int res = 0;
while(b > 0)
{
if(b & 1) res = (res + a) % mod;
a = (a + a) % mod;
b >>= 1;
}
return res;
}
int exgcd(int a, int b, int &x, int &y)
{
if(b == 0){x = 1; y = 0; return a;}
int gcd = exgcd(b, a % b, x, y);
int tp = x;
x = y; y = tp - a / b * y;
return gcd;
}
int excrt()
{
int x, y, k;
int M = bi[1], ans = ai[1];
for(int i = 2; i <= n; ++i)
{
int a = M, b = bi[i], c = (ai[i] - ans % b + b) % b;
int gcd = exgcd(a, b, x, y), bg = b / gcd;
if(c % gcd != 0) return -1;
x = mul(x, c / gcd, bg);
ans += x * M;
M *= bg;
ans = (ans % M + M) % M;
}
ans = (ans % M + M) % M;
if(ans == 0) ans = M;
return ans;
}
int phi(int x)
{
int o = x;
for(int i = 2; i * i <= x; ++i)
{
if(x % i == 0)
{
while(x % i == 0) x /= i;
o = o / i * (i - 1);
}
}
if(x > 1) o = o / x * (x - 1);
return o;
}
int qpow(int x, int y, int mod)
{
int res = 1ll;
while(y)
{
if(y & 1ll) res = js(res * x, mod);
x = js(x * x, mod);
y >>= 1ll;
}
return x;
}
int solve(int l, int r, int mod)
{
if(l == r || mod == 1) return js(l, mod);
return qpow(l, solve(l + 1, r, phi(mod)), mod);
}
signed main()
{
a = read(), b = read(), n = read(), p = read();
for(int i = 1; i <= n; ++i)
{
bi[i] = read();
ai[i] = (1 - i + bi[i]) % bi[i];
Lcm = lcm(Lcm, bi[i]);
}
if(n > b) return puts("NO"), 0;
int x = Lcm, y = excrt();
if(y == -1) return puts("NO"), 0;
for(int i = 1; i <= n; ++i)
if(gcd(x, y + i - 1) != bi[i])
return puts("NO"), 0;
if(y < 1 || x < 1 || y + n - 1 > b || x > a)
return puts("NO"), 0;
puts("YES");
return 0;
}
本文来自博客园,作者:蒟蒻orz,转载请注明原文链接:https://www.cnblogs.com/orzz/p/18122066
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通