BZOJ-1407 [Noi2002]Savage(exgcd)
题目描述
数据范围:\(1\leq n\leq 15,1\leq C_i,P_i\leq 100,0\leq L_i\leq 10^6\),输入数据保证有解,且 \(M\leq 10^6\)。
分析
给出 \(n\) 组 \(C_i,P_i,L_i\),求最小的 \(M\) 使得对于任意的 \(i,j(1\leq i,j\leq n)\)
\[C_i+P_i\times x\equiv C_j+P_j\times x\pmod {M}
\]
不成立。
则:
\[C_i+P_i\times x+My=C_j+P_j\times x\\(P_i-P_j)x+My=C_j-C_i
\]
\(M\) 最大 \(10^6\),从小到大枚举 \(M\),用扩展欧几里得算法检验是否有解。若无解,\(M\) 即为所求;若有解,判断 \(x_{\min}\leq L_i\) 且 \(x_{\min}\leq L_j\) 是否成立,若成立说明有解,继续枚举;若不成立,\(M\) 即为所求。
时间复杂度 \(O(Mn^2\log C_i)\)。
代码
#include<bits/stdc++.h>
using namespace std;
int n;
long long C[1010],P[1010],L[1010];
long long exgcd(long long a,long long b,long long &x,long long &y)
{
if(!b)
{
x=1;
y=0;
return a;
}
long long gcd=exgcd(b,a%b,y,x);
y=y-x*(a/b);
return gcd;
}
bool check(int M)
{
for(int i=1;i<=n;i++)
{
for(int j=i+1;j<=n;j++)
{
long long a=P[i]-P[j];
long long b=M;
long long c=C[j]-C[i];
long long x,y;
long long gcd=exgcd(b,a%b,y,x);
if(c%gcd!=0)
continue;
a=a/gcd;b=b/gcd;c=c/gcd;
if(b<0)
b=-b;
x=(x*c%b+b)%b;
if(x<=L[i]&&x<=L[j])
return 0;
}
}
return true;
}
int main()
{
cin>>n;
long long maxn=0;
for(int i=1;i<=n;i++)
{
scanf("%d %d %d",&C[i],&P[i],&L[i]);
maxn=max(maxn,C[i]);
}
for(int i=maxn;;i++)
{
if(check(i))
{
printf("%d\n",i);
return 0;
}
}
return 0;
}
posted on 2020-12-06 14:20 DestinHistoire 阅读(33) 评论(0) 收藏 举报