QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#462764#7087. Counting PolygonsteraqqqWA 387ms237912kbC++144.1kb2024-07-04 03:15:032024-07-04 03:15:05

Judging History

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

  • [2024-07-04 03:15:05]
  • 评测
  • 测评结果:WA
  • 用时:387ms
  • 内存:237912kb
  • [2024-07-04 03:15:03]
  • 提交

answer

#include <bits/stdc++.h>

using namespace std;
using ll = long long;

constexpr int MOD = 1'000'000'007;
constexpr int N = 10'000'228;
constexpr int M = 2*N;

int minp[N+1], fact[M+1], rfct[M+1], phi[N+1];
int rev(int a, int m = MOD) {
    return a == 1 ? 1 : m - (ll)m*rev(m%a,a)/a;
}
int c(int n, int k) {
    return 0 <= k && k <= n ? (ll)fact[n]*rfct[k]%MOD*rfct[n-k]%MOD : 0;
}

void mod_add(int& a, int b) {
    a += b;
    if (a >= MOD) a -= b;
}

void mod_sub(int& a, int b) {
    a -= b;
    if (a < 0) a += MOD;
}

int cnt(int n, int mp, int sn) {
    if (n < 0) return 0;
    if (sn) {
        int a = cnt(n, mp+1, sn-1);
        mod_add(a, cnt(n+1, mp+1, sn-1));
        return a;
    } else {
        const int a = n%2 ? 0 : c(n/2-1, mp-1);
        return a;
    }
}

int solve(int n, int m) {
    vector<int> divs{{1}};
    for (int j = m; j != 1; ) {
        const int p = minp[j], s = divs.size();
        // cout << j << ", p=" << p << endl;
        int k = 0;
        while (j % p == 0) j /= p, ++k;
        for (int i = 0; i < s*k; ++i)
            divs.push_back(divs[i]*p);
    }

    int ans = 0;
    for (int d : divs) {
        if (d == m) {
            mod_add(ans, c(n-1, m-1));
            ans = (ans + (ll)(MOD - m)*c(n/2, m-1))%MOD;
            // cout << "d=" << d << ": " << ans << " " << 1 << endl;
        } else {
            const int cnt = m / d;
            if (n % cnt == 0)
                ans = (ans + (ll)c(n/cnt-1, d-1)*phi[cnt])%MOD;
            // cout << "d=" << d << ": " << ans << " " << phi[cnt] << endl;
        }
    }
    // cerr << ans << " half" << endl;

    if (m % 2) {
        ans = (ans + (ll)m*cnt(n, m/2, 1))%MOD;
        ans = (ans + (ll)(MOD-m)*cnt(n/2+1, m/2, 1))%MOD;
    } else {
        ans = (ans + (ll)(m/2)*cnt(n, m/2, 0))%MOD;
        ans = (ans + (ll)(m/2)*cnt(n, m/2-1, 2))%MOD;
        ans = (ans + (ll)(MOD-m)*cnt(n/2+1, m/2-1, 2))%MOD;
    }
    // cerr << ans << "!" << endl;

    ans = (ll)ans*rev(2*m)%MOD;
    if (ans < 0) ans += MOD;
    return ans;
}

int solve_brute(int n, int m, int max, vector<int>& st) {
    if (n < m) return 0;
    if (!m) {
        if (n != 0) return 0;
        auto v = st;
        for (int t = 2; t--; ) {
            reverse(v.begin(), v.end());
            for (int i = 0; i < st.size(); ++i) {
                rotate(v.begin(), v.begin()+1, v.end());
                if (v < st) return 0;
            }
        }
        // for (int x : st) cout << x << ' ';
        // cout << endl;
        return 1;
    }
    int ans = 0;
    st.push_back(0);
    for (int x = 1; x <= n && 2*x < max; ++x) {
        st.back() = x;
        ans += solve_brute(n-x, m-1, max, st);
    }
    st.pop_back();
    return ans;
}

int solve_brute(int n, int m) {
    vector<int> st;
    int ans = solve_brute(n, m, n, st);
    return ans;
}

int main() {
    ios::sync_with_stdio(0); cin.tie(0);
    
    for (int i = 2; i <= N; ++i) {
        if (minp[i]) continue;
        minp[i] = i;
        if ((ll)i*i > N) continue;
        for (int j = i*i; j <= N; j += i)
            if (!minp[j]) minp[j] = i;
    }

    phi[1] = 1;
    for (int i = 2; i <= N; ++i) {
        const int p = minp[i];
        const int j = i / p;
        if (p == minp[j]) phi[i] = phi[j] * p;
        else              phi[i] = phi[j] * (p-1);
    }

    fact[0] = 1;
    for (int i = 1; i <= M; ++i) fact[i] = (ll)fact[i-1]*i%MOD;
    rfct[M] = rev(fact[M]);
    for (int i = M; i >= 1; --i) rfct[i-1] = (ll)rfct[i]*i%MOD;

    for (int n = 1; n <= 20; ++n) {
        // cerr << "m=" << m << endl;
        for (int m = 3; m <= n; ++m) {
            int pans = solve(n, m);
            int jans = solve_brute(n, m);
            if (pans != jans) {
                cout << "WA!" << endl;
                cout << n << " " << m << endl;
                cout << "pans=" << pans << endl;
                cout << "jans=" << jans << endl;
                exit(0);
            }
        }
    }

    int t; cin >> t;
    while (t--) {
        int n, m; cin >> n >> m;
        int ans = solve(n, m);
        cout << ans << '\n';
    }
}

Details

Tip: Click on the bar to expand more detailed information

Test #1:

score: 100
Accepted
time: 360ms
memory: 237912kb

input:

4
3 3
4 3
5 3
7 4

output:

1
0
1
3

result:

ok 4 tokens

Test #2:

score: -100
Wrong Answer
time: 387ms
memory: 237872kb

input:

10000
8708700 6531525
8062080 4031040
7068600 2356200
3659040 332640
7309575 2088450
5503680 1572480
7162848 3581424
9831360 7724640
6306300 5045040
5783400 2891700
4677120 2338560
5110560 786240
9525600 2381400
6955200 4173120
8229375 3291750
7068600 5405400
9639000 3213000
5969040 2984520
5274360 ...

output:

45666775
386843180
867437616
253300932
482697442
649018062
157961376
79708753
910840671
748709468
762771581
839851514
132357899
326189264
36752374
993212465
73044078
493706137
506234162
982243306
632144614
295169771
380670445
257151958
690742488
609943733
903896971
483810853
402932842
865811879
3675...

result:

wrong answer 1st words differ - expected: '70575804', found: '45666775'