数学题啊
由题意,x是密码,那么(x+x)%n是密码,(2x+x)%n也是密码…… x*k%n是密码;①
x*k-n*c=GCD(x,n)
观察上面这个式子,一定有一个整数t,使得x*t%n==GCD(x,n),由①可得,GCD(x,n)也是密码。(扩展欧几里得)
于是得出
结论1:如果x是密码,那么GCD(x,n)也是密码。
设x,y是两个密码,那么(p*x+q*y)%n也是密码。②
a*x+b*y=GCD(x,y)一定有解,所以a*x+b*y≡GCD(x,y) (mod n)一定有解③
因为:a*x+b*y ≡ a*x+b*y+p*n*x+q*n*x (mod n)
即 : (a+p*n)*x+(b+q*n)*y ≡ a*x+b*y (mod n) ④
扫描二维码关注公众号,回复:
4208854 查看本文章
由③④得:
(a+p*n)*x+(b+q*n)*y≡GCD(x,y)一定有解
由②得:((a+p*n)*x+(b+q*n) )%n 一定是密码(a+p*n相当于②里面的p),
④=>a*x+b*y是密码 , 进而③=>GCD(x,y) 是密码。
于是得出
结论2:x,y是密码,那么GCD(x,y)也是密码
实现方法:
先设a[k]=GCD(n,a[k]),可以先在根号时间复杂度内处理出a[k]的所有因子,存在q数组中,
接着去除所有是GCD(a[i],a[k])的因数,设去除后最小的因子为x,那么答案是n/x。
代码
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define LL long long #define M 250005 using namespace std; int f[M],k; LL a[M],q[M],n; LL gcd(LL a,LL b) { if(a<b) swap(a,b); return b?gcd(b,a%b):a; } int main() { scanf("%lld%d",&n,&k); for(int i=1;i<=k;i++) scanf("%lld",&a[i]); a[k]=gcd(a[k],n); for(int i=1;i<k;i++) a[i]=gcd(a[i],a[k]); int t=0; for(LL i=1;i*i<=a[k];i++) { if(a[k]%i==0)//i是a[k]的因子 { q[++t]=i; if(a[k]/i!=i) q[++t]=a[k]/i;//a[k]/i也是a[k]的因子 } } sort(q,q+t+1); for(int i=1;i<k;i++) { f[lower_bound(q+1,q+t+1,a[i])-q]=1; } for(int i=1;i<=t;i++) if(f[i]) for(int j=1;j<i;j++) if(q[i]%q[j]==0) f[j]=1; int p; for(p=1;f[p];p++); printf("%lld",n/q[p]); return 0; }
有点复杂好好想想