P8193 [USACO22FEB] Sleeping in Class P
P8193 [USACO22FEB] Sleeping in Class P
提供一个不需要 Pollard - rho 的做法。
记
考虑这样一个朴素的暴力:对每个
注意到实际上只需求
问题只剩下分解质因数了。不想写 Pollard - rho 怎么办?考虑只分解到
时间复杂度
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int N = 2e5 + 5;
ll n, q, a[N], pr[N];
int pw[N], cnt, ppw[N];
map <ll, ll> mp;
int f[N];
int calc(int *pw) {
int res = 0;
for(int i = 1; i <= cnt; i++) res += pw[i] * ppw[i];
return res;
}
ll rev(int x) {
ll res = 1;
for(int i = 1; i <= cnt; i++) {
int d = x / ppw[i] % (pw[i] + 1);
for(int j = 1; j <= d; j++) res *= pr[i];
} return res;
}
int fix, cpw[N];
void dfs(int id) {
if(id > cnt) {
int cur = calc(cpw);
f[cur - ppw[fix]] += f[cur];
return;
} for(int i = pw[id]; i >= (id == fix); i--) cpw[id] = i, dfs(id + 1);
}
void check() {
ll tmp = a[n];
for(int i = 2; i <= 1e6; i++)
if(tmp % i == 0) {
pr[++cnt] = i;
while(tmp % i == 0) pw[cnt]++, tmp /= i;
}
if(tmp > 1e12) return;
if(tmp > 1) pr[++cnt] = tmp, pw[cnt] = 1;
ppw[cnt] = 1;
for(int i = cnt - 1; ~i; i--) ppw[i] = ppw[i + 1] * (pw[i + 1] + 1);
for(int i = 1; i < n; i++) {
ll tmp = a[i];
for(int j = 1; j <= cnt; j++) {
int cur = 0;
while(tmp % pr[j] == 0) cur++, tmp /= pr[j];
cpw[j] = min(pw[j], cur);
} f[calc(cpw)]++;
}
for(int i = 1; i <= cnt; i++) fix = i, dfs(1);
for(int i = 0; i < ppw[0]; i++) mp[rev(i)] = n - 1 + a[n] / rev(i) - 1 - f[i] * 2;
}
int main() {
cin >> n;
for(int i = 1; i <= n; i++) cin >> a[i], a[i] += a[i - 1];
check(), cin >> q;
for(int i = 1; i <= q; i++) {
ll x; cin >> x;
if(a[n] % x) {puts("-1"); continue;}
if(!mp[x]) {
ll ans = 0;
for(int j = 1; j < n; j++) ans += a[j] % x == 0;
mp[x] = n - 1 + a[n] / x - 1 - ans * 2;
}
cout << mp[x] << "\n";
}
return 0;
}
/*
stupid mistakes:
进制转换写错了
rev : res *= pr[i] -> *= pr[j]
*/