题解 保险箱
上面题解里的式子不再写一遍了
- 与「在不在mod n加法下的群中(能否通过加减得到这个数)」相关的问题可以尝试通过裴蜀定理转化为是否同余于gcd之类
于是考虑如何在可以接受的复杂度内判断一个 \(g\) 是否合法
对 \(k\) 个数都判断一遍肯定T了,发现我们只需要判断是否整除,于是可以预处理
首先一定有 \(g \mid gcd(m_k, n)\),所以可以将 \(m_i\) 都变成 \(gcd(m_i, m_k)\) 以去掉没有用的因子
然后考虑有且仅有所有 \(m_i\) 的因数不可以作为 \(g\)
所以可以记搜分解所有 \(m_i\),同时标记所有不合法的 \(g\)
然后枚举 \(g\) check即可
Code:
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 300010
#define ll long long
// #define int long long
char buf[1<<21], *p1=buf, *p2=buf;
inline ll read() {
ll ans=0, f=1; char c=getchar();
while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
return ans*f;
}
ll n, k;
ll a[N];
namespace force{
int uni[N], usiz, x;
bool vis[100000010];
inline void md(int& a, int b) {a+=b; a=a>=n?a-n:a;}
void solve() {
// cout<<double(sizeof(vis))/1000/1000<<endl;
x=a[k];
for (int i=1; i<=n; ++i) {
vis[a[i]]=1;
int tem=(a[i]+x)%n;
while (tem!=a[i]) {
vis[tem]=1;
md(tem, x);
}
}
int ans=0;
for (int i=0; i<n; ++i) if (!vis[i]) ++ans;
printf("%d\n", ans);
exit(0);
}
}
namespace task1{
int uni[N], usiz, x;
void solve() {
x=a[k];
for (int i=1; i<k; ++i) uni[++usiz]=a[i]%x;
sort(uni+1, uni+usiz+1);
usiz=unique(uni+1, uni+usiz+1)-uni-1;
int ans=n;
for (int i=1; i<=usiz; ++i) {
ans-=(n-uni[i])/x;
}
cout<<ans<<endl;
}
}
namespace task{
unordered_map<ll, bool> mp;
ll div[N], dcnt;
void dfs(ll n) {
if (mp.find(n)!=mp.end()) return ;
mp[n]=1;
for (int i=1; i<=dcnt; ++i) if (n%div[i]==0) dfs(n/div[i]);
}
void solve() {
ll t=__gcd(a[k], n), t2=t;
for (ll i=2; i*i<=t; ++i) {
if (t2%i==0) {
div[++dcnt]=i;
do {t2/=i;} while (t2%i==0);
}
}
if (t2>1) div[++dcnt]=t2;
for (int i=1; i<k; ++i) dfs(__gcd(a[i], t));
ll i=1;
for (; i*i<=t; ++i) if (t%i==0 && mp.find(i)==mp.end()) {printf("%lld\n", n/i); exit(0);}
for (--i; i; --i) if (t%i==0 && mp.find(t/i)==mp.end()) {printf("%lld\n", n/(t/i)); exit(0);}
}
}
signed main()
{
freopen("b.in", "r", stdin);
freopen("b.out", "w", stdout);
n=read(); k=read();
for (int i=1; i<=k; ++i) a[i]=read();
// force::solve();
task::solve();
return 0;
}