QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#800282 | #9619. 乘积,欧拉函数,求和 | DarwinA66 | TL | 1468ms | 6608kb | C++20 | 4.0kb | 2024-12-06 04:36:41 | 2024-12-06 04:36:41 |
Judging History
answer
#include<bits/stdc++.h>
#define ll long long
#define int ll
using namespace std;
const int N = 3010;
ll mod = 998244353;
ll n;
ll pri[] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59};
ll a[N], prime_factors_mask[N], highest_prime_factor[N];
ll id[N];
ll st[1 << 16];
ll dp[1 << 16];
ll add_dp[1 << 16];
ll tp[1 << 16];
ll add_tp[1 << 16];
// Fast power function
ll fastpow(ll x, ll p) {
ll base = x, res = 1ll;
while (p) {
if (p & 1ll) res = (res * base) % mod;
base = (base * base) % mod;
p >>= 1ll;
}
return res;
}
// Modular inverse function using Fermat's Little Theorem
ll mod_inverse(ll x) {
return fastpow(x, mod - 2ll);
}
// Prime factorization function
void prime_factorization(ll index) {
ll number = a[index], largest_prime = 0ll;
for (int j = 0; j < 16; j++) {
while (number % pri[j] == 0) {
number /= pri[j];
prime_factors_mask[index] |= 1ll << j; // Set the corresponding prime factor bit
largest_prime = pri[j];
}
}
if (number > 53) highest_prime_factor[index] = number;
else highest_prime_factor[index] = largest_prime;
}
// Comparison function for sorting
bool cmp(ll x, ll y) {
return highest_prime_factor[x] < highest_prime_factor[y];
}
// Main function
signed main() {
scanf("%lld", &n);
for (int i = 1; i <= n; i++) {
scanf("%lld", &a[i]);
id[i] = i;
prime_factorization(i);
}
sort(id + 1, id + 1 + n, cmp); // Sort based on the highest prime factor
for (ll mask = 0; mask < (1ll << 16); mask++) {
ll temp = 1ll;
for (int j = 0; j < 16; j++) {
if (mask & (1ll << j)) {
temp = (temp * (pri[j] - 1ll)) % mod;
temp = (temp * mod_inverse(pri[j])) % mod;
}
}
st[mask] = temp;
dp[mask] = 0ll;
tp[mask] = 0ll;
}
dp[0] = 1ll;
// DP computation loop
for (int i = 1; i <= n; i++) {
for (ll mask = 0; mask < (1ll << 16); mask++) {
add_dp[mask] = 0ll;
add_tp[mask] = 0ll;
}
if (highest_prime_factor[id[i]] <= 53) {
// Processing numbers with prime factors <= 53
for (ll mask = 0; mask < (1ll << 16); mask++) {
if (dp[mask] >= 1ll) {
add_dp[mask | prime_factors_mask[id[i]]] = (add_dp[mask | prime_factors_mask[id[i]]] + ((dp[mask] * a[id[i]]) % mod)) % mod;
}
}
for (ll mask = 0; mask < (1ll << 16); mask++) {
dp[mask] = (dp[mask] + add_dp[mask]) % mod;
}
} else {
// Processing numbers with larger prime factors
for (ll mask = 0; mask < (1ll << 16); mask++) {
if (dp[mask] >= 1ll) {
ll num = (dp[mask] * a[id[i]]) % mod;
num = (((num * (highest_prime_factor[id[i]] - 1ll)) % mod) * mod_inverse(highest_prime_factor[id[i]])) % mod;
add_dp[mask | prime_factors_mask[id[i]]] = (add_dp[mask | prime_factors_mask[id[i]]] + num) % mod;
}
if (tp[mask] >= 1ll) {
add_tp[mask | prime_factors_mask[id[i]]] = (add_tp[mask | prime_factors_mask[id[i]]] + ((tp[mask] * a[id[i]]) % mod)) % mod;
}
}
for (ll mask = 0; mask < (1ll << 16); mask++) {
tp[mask] = (((tp[mask] + add_dp[mask]) % mod) + add_tp[mask]) % mod;
if (i == n || highest_prime_factor[id[i + 1]] != highest_prime_factor[id[i]]) {
dp[mask] = (dp[mask] + tp[mask]) % mod;
tp[mask] = 0ll;
}
}
}
}
// Calculate the final result
ll ans = 0ll;
for (ll mask = 0; mask < (1ll << 16); mask++) {
ans = (ans + (dp[mask] * st[mask]) % mod) % mod;
}
printf("%lld\n", ans);
return 0;
}
Details
Tip: Click on the bar to expand more detailed information
Test #1:
score: 100
Accepted
time: 131ms
memory: 6416kb
input:
5 1 6 8 6 2
output:
892
result:
ok single line: '892'
Test #2:
score: 0
Accepted
time: 128ms
memory: 6548kb
input:
5 3 8 3 7 8
output:
3157
result:
ok single line: '3157'
Test #3:
score: 0
Accepted
time: 1468ms
memory: 6608kb
input:
2000 79 1 1 1 1 1 1 2803 1 1 1 1 1 1 1609 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2137 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 613 1 499 1 211 1 2927 1 1 1327 1 1 1123 1 907 1 2543 1 1 1 311 2683 1 1 1 1 2963 1 1 1 641 761 1 1 1 1 1 1 1 1 1 1 1 1489 2857 1 1 1 1 1 1 1 1 1 1 1 1 1 967 1 821 1 1 1 1 2143 1861...
output:
50965652
result:
ok single line: '50965652'
Test #4:
score: -100
Time Limit Exceeded
input:
2000 1 1 1 1 1 1 1 1 353 1 1 1 557 1 1 1 1 1 1 1 1 1 1 1 1423 1 1 1327 1 1 1 907 1 1 1 1 1 2971 1 1 1 2531 1 1 1 1 1 1 1 1 1 2099 1 1 1 1 1 1 1 1 1 1 1 1 1 1 199 2999 1 727 1 1 1 1 1 1 1 71 1 1 1 1 1 1 2503 1 176 1 1 1 1 1 1 1361 1013 1 1 1 1 1 1 1 2699 1 1 1 1 1 1 1 1 1 2897 1 1 1 1 1637 1 1 1367 1...