QOJ.ac

QOJ

ID题目提交者结果用时内存语言文件大小提交时间测评时间
#800282#9619. 乘积,欧拉函数,求和DarwinA66TL 1468ms6608kbC++204.0kb2024-12-06 04:36:412024-12-06 04:36:41

Judging History

你现在查看的是最新测评结果

  • [2024-12-06 04:36:41]
  • 评测
  • 测评结果:TL
  • 用时:1468ms
  • 内存:6608kb
  • [2024-12-06 04:36:41]
  • 提交

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;
}

详细

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...

output:


result: