P3518

· · 题解

分析 --- - 每个输入的数据与 $n$ 的 $\gcd$ 求出 - 如果 $a[i]$ 是密码,那么所有 $a[i]$ 与 $n$ 最大公约数的倍数也是密码; - 如果 $a[i]$ 不是密码,那么所有a[i]与n最大公约数的倍数也都不是密码 - 那么从 $1 $到 $\sqrt{ a[k] }$ ~~这样分块就能使时间复杂度降低)~~ 寻找,最小且符合条件的就是密码。 代码 --- ```C++ #include<bits/stdc++.h> #define ll long long #define ull unsigned ll using namespace std; const ll maxn=2000000+5; //数组开小了就不会过 ll a[maxn],num=0,ans=0; inline ll read() { ll k=0; int fu=1; char ch=getchar(); (ch=='-')?fu=-1:k=ch-'0'; while((ch=getchar())!=' '&&ch!='\n'){ k=k*10+ch-'0'; } return fu*k; //ÌÓ } inline ll gcd(long long a,long long b) { return b?gcd(b,a%b):a; }//Ò²¿ÉÒÔÓÃ×Ô´øµÄ __gcd(item x,item b) inline bool check(int x) { for(ll i=1; i<num; i++) { if(a[i]%x==0) return false; } return true; } int main() { ll n=read(),k=read(); for(ll i=1; i<=k; i++) a[i]=read(); for(ll i=1; i<=k; i++) { a[i]=gcd(a[i],n); // a[i]=__gcd(a[i],n); } sort(a+1,a+k); for(ll i=1; i<=k; i++) if(a[i]!=a[i-1]) a[++num]=a[i]; ll sak=sqrt(a[k]); for(ll i=1; i<=sak; i++) { if(a[k]%i==0) { if(check(i)==true) { ans=n/i; break; } else if(check(a[k]/i)==true) ans=n/a[k]*i; } } printf("%lld\n",ans); return 0; } ``` ```C++ #include<bits/stdc++.h> #define ll long long #define ull unsigned ll using namespace std; const ll maxn=2000000+5; ll a[maxn],num=0,ans=0; inline ll read() { ll k=0; int fu=1; char ch=getchar(); (ch=='-')?fu=-1:k=ch-'0'; while((ch=getchar())!=' '&&ch!='\n'){ k=k*10+ch-'0'; } return fu*k; //ÌÓ } inline ll gcd(long long a,long long b) { return b?gcd(b,a%b):a; }//Ò²¿ÉÒÔÓÃ×Ô´øµÄ __gcd(item x,item b) inline bool check(int x) { for(ll i=1; i<num; i++) { if(a[i]%x==0) return false; } return true; } int main() { ll n=read(),k=read(); for(ll i=1; i<=k; i++) a[i]=read(); for(ll i=1; i<=k; i++) { a[i]=gcd(a[i],n); // a[i]=__gcd(a[i],n); } sort(a+1,a+k); for(ll i=1; i<=k; i++) if(a[i]!=a[i-1]) a[++num]=a[i]; ll sak=sqrt(a[k]); for(ll i=1; i<=sak; i++) { if(a[k]%i==0) { if(check(i)==true) { ans=n/i; break; } else if(check(a[k]/i)==true) ans=n/a[k]*i; } } printf("%lld\n",ans); return 0; } ```