QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#800279#9619. 乘积,欧拉函数,求和DarwinA66TL 1595ms6552kbC++204.2kb2024-12-06 04:28:402024-12-06 04:28:41

Judging History

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

  • [2024-12-06 04:28:41]
  • 评测
  • 测评结果:TL
  • 用时:1595ms
  • 内存:6552kb
  • [2024-12-06 04:28:40]
  • 提交

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], s[N], v[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];

// Function to compute fast power
ll fastpow(ll x, ll p) {
    ll base = x;
    ll res = 1ll;
    while (p) {
        if (p & 1ll) res = (res * base) % mod;
        base = (base * base) % mod;
        p >>= 1ll;
    }
    return res;
}

// Function to compute modular inverse using Fermat's Little Theorem
ll mod_inverse(ll x) {
    return fastpow(x, mod - 2ll);
}

// Prime factorization of a number
void prime_factorization(ll i) {
    ll temp = a[i];
    ll max_p = 0ll;
    // Loop over the first 16 primes to factor the number
    for (int j = 0; j < 16; j++) {
        while (temp % pri[j] == 0) {
            temp /= pri[j];
            s[i] |= 1ll << j;  // Set the corresponding bit for this prime
            max_p = pri[j];
        }
    }
    // If remaining number is greater than 53, store it directly; otherwise store the largest prime divisor
    if (temp > 53) v[i] = temp;
    else v[i] = max_p;
}

// Comparison function for sorting
bool cmp(ll x, ll y) {
    return v[x] < v[y];
}

// Main solution function
signed main() {
    scanf("%lld", &n);
    
    // Input array and initialize id array
    for (int i = 1; i <= n; i++) {
        scanf("%lld", &a[i]);
        id[i] = i;
        prime_factorization(i);
    }


    // Sort ids based on the value of v[]
    sort(id + 1, id + 1 + n, cmp);

    // Initialize DP and bitmask-related arrays
    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;

    // Main loop over elements
    for (int i = 1; i <= n; i++) {
        // Reset temporary arrays for DP updates
        for (ll mask = 0; mask < (1ll << 16); mask++) {
            add_dp[mask] = 0ll;
            add_tp[mask] = 0ll;
        }

        if (v[id[i]] <= 53) {
            // Process numbers with prime divisors <= 53
            for (ll mask = 0; mask < (1ll << 16); mask++) {
                if (dp[mask] >= 1ll) {
                    add_dp[mask | s[id[i]]] = (add_dp[mask | s[id[i]]] + ((dp[mask] * a[id[i]]) % mod)) % mod;
                }
            }
            // Update DP array after processing all elements
            for (ll mask = 0; mask < (1ll << 16); mask++) {
                dp[mask] = (dp[mask] + add_dp[mask]) % mod;
            }
        } else {
            // Process 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 * (v[id[i]] - 1ll)) % mod) * mod_inverse(v[id[i]])) % mod;
                    add_dp[mask | s[id[i]]] = (add_dp[mask | s[id[i]]] + num) % mod;
                }
                if (tp[mask] >= 1ll) {
                    add_tp[mask | s[id[i]]] = (add_tp[mask | s[id[i]]] + ((tp[mask] * a[id[i]]) % mod)) % mod;
                }
            }

            // Update temporary DP and handle final updates
            for (ll mask = 0; mask < (1ll << 16); mask++) {
                tp[mask] = (((tp[mask] + add_dp[mask]) % mod) + add_tp[mask]) % mod;
                if (i == n || v[id[i + 1]] != v[id[i]]) {
                    dp[mask] = (dp[mask] + tp[mask]) % mod;
                    tp[mask] = 0ll;
                }
            }
        }
    }

    // Final result computation by summing up all DP states
    ll ans = 0ll;
    for (ll mask = 0; mask < (1ll << 16); mask++) {
        ans = (ans + (dp[mask] * st[mask]) % mod) % mod;
    }

    // Output the final result
    printf("%lld\n", ans);
    return 0;
}

Details

Tip: Click on the bar to expand more detailed information

Test #1:

score: 100
Accepted
time: 133ms
memory: 6412kb

input:

5
1 6 8 6 2

output:

892

result:

ok single line: '892'

Test #2:

score: 0
Accepted
time: 128ms
memory: 6368kb

input:

5
3 8 3 7 8

output:

3157

result:

ok single line: '3157'

Test #3:

score: 0
Accepted
time: 1595ms
memory: 6552kb

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: