QOJ.ac

QOJ

ID题目提交者结果用时内存语言文件大小提交时间测评时间
#348852#8340. 3 Sumucup-team197#TL 1ms3668kbC++206.1kb2024-03-09 21:49:522024-03-09 21:49:54

Judging History

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

  • [2024-09-20 10:20:30]
  • hack成功,自动添加数据
  • (/hack/848)
  • [2024-03-18 21:48:05]
  • hack成功,自动添加数据
  • (/hack/579)
  • [2024-03-18 21:45:33]
  • hack成功,自动添加数据
  • (/hack/578)
  • [2024-03-09 21:49:54]
  • 评测
  • 测评结果:TL
  • 用时:1ms
  • 内存:3668kb
  • [2024-03-09 21:49:52]
  • 提交

answer

#pragma GCC optimize("unroll-loops")

#include <bits/stdc++.h>

using namespace std;

using ll = long long;
using vi = vector<int>;
using vvi = vector<vector<int>>;
using vll = vector<long long>;
using vvll = vector<vector<long long>>;
using vb = vector<bool>;

using i128 = __int128_t;

const int MAXK = 20'100;
const int D = 18;
const int S = MAXK / D;
const ll M = 1'000'000'000LL * 1'000'000'000;

mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());

const ll MOD = 1e9 + 7;

ll pow10[D];
ll rnd[S];
void precomp() {
    pow10[0] = 1;
    for(int i = 1; i < D; i++) {
        pow10[i] = 10 * pow10[i-1];
    }
    for(int i = 0; i < S; i++) {
        rnd[i] = rng() % MOD;
    }
}

struct BigInt {
    ll num[S];

    inline friend BigInt operator+(const BigInt &a, const BigInt &b) {
        BigInt res;
        int carry = 0;
        for(int i = 0; i < S; i++) {
            res.num[i] = carry + a.num[i] + b.num[i];
            carry = 0;
            if(res.num[i] >= M) {
                res.num[i] -= M;
                carry = 1;
            }
        }
        return res;
    }

    inline friend BigInt inegate(const BigInt &a, int k) {
        BigInt res;
        for(int i = 0; i < S; i++) {
            if(i * D > k) break;
            ll limit = M;
            if((i+1) * D > k) [[unlikely]]{
                limit = pow10[k - i * D];
            }
            res.num[i] = limit - 1 - a.num[i];
        }
        res.norm(k);
        return res;
    }

    inline friend BigInt plusmod(const BigInt &a, const BigInt &b, int k) {
        BigInt c = a + b;
        c.norm(k);
        return c;
    }

    inline void norm(int k) {
        int big = k / D;
        int idx = k % D;
        if(num[big] >= pow10[idx]) [[unlikely]] {
            num[big] -= pow10[idx];
            for(int i = 0; i < S; i++) {
                num[i] += 1;
                if(num[i] >= M) [[likely]] {
                    num[i] = 0;
                } else {
                    break;
                }
            }
        }

        for(int i = 0; i < S; i++) {
            if(i * D > k) break;
            ll limit = M;
            if((i+1) * D > k) [[unlikely]]{
                limit = pow10[k - i * D];
            }
            if(num[i] != limit-1) {
                return;
            }
        }
        memset(num, 0, sizeof(num));
    }
    
    inline void add_digit(int d, int pos, int k) {
        int big = pos / D;
        int idx = pos % D;
        num[big] += pow10[idx] * d;
        for(int i = big; i < S; i++) {
            if(num[i] >= M) [[likely]] {
                num[i] -= M;
                num[i+1]++;
            } else {
                break;
            }
        }
    }

    ll hash() {
        ll result = 0;
        for(int i = 0; i < S; i++) {
            result = (result + rnd[i] * num[i]) % MOD;
        }
        return result;
    }
};

void solve(){
    ll n;
    int k;
    cin >> n >> k;

    vector<BigInt> nums;
    for(int i = 0; i < n; i++) {
        string s;
        cin >> s;
        reverse(s.begin(), s.end());
        int len = s.size();
        BigInt t;
        memset(t.num, 0, sizeof(t.num));
        vi carry(S);
        int of = 0;
        for(int i = 0; i < len; i++) {
            // cerr << i << endl;
            t.add_digit(s[i]-'0', i % k, k);
        //     int g = i % k;
        //     int big = g / D;
        //     int small = g % D;
        //     t.num[big] += pow10[small] * (s[i]-'0');
        //     if((big+1) * D > k) [[unlikely]] {
        //         ll limit = pow10[((len-1) % D) + 1];
        //         if(t.num[big] >= limit) {
        //             t.num[big] -= limit;
        //             of++;
        //         }
        //     } else {
        //         if(t.num[big] >= M) {
        //             t.num[big] -= M;
        //             carry[big]++;
        //         }
        //     }
        // }
        // int c = 0;
        // for(int i = 0; i < S; i++) {
        //     if((i+1) * D > k) {
        //         t.num[i] += carry[i] + c;
        //         ll limit = pow10[((len-1) % D) + 1];
        //         if(t.num[i] >= limit) of++;
        //         break;
        //     }
        //     t.num[i] += carry[i] + c;
        //     if(t.num[i] > M) {
        //         c++;
        //     }
        }
        // cerr << of << endl;
        t.norm(k);
        nums.push_back(t);
    }

    // for(int i = 0; i < n; i++) {
    //     for(int j = 0; j < 4; j++) {
    //         cout << nums[i].num[j] << ' ';
    //     }
    //     cout << endl;
    // }

    vi nh;
    map<ll, int> negate_hash;
    for(int i = 0; i < n; i++) {
        BigInt neg = inegate(nums[i], k);
        // cerr << neg.num[0] << endl;
        ll h = neg.hash();
        nh.push_back(h);
        negate_hash[h]++;
    }

    int ans = 0;
    int alldiff = 0;
    int allsame = 0;
    int twosame = 0;
    for(int i = 0; i < n; i++) {
        for(int j = i; j < n; j++) {
            BigInt res = plusmod(nums[i], nums[j], k);
            ll hsh = res.hash();

            int tot = negate_hash[hsh];
            int same = (nh[i] == hsh) + (nh[j] == hsh && i != j);
            int diff = tot - same;
            alldiff += diff * (i != j) * 2;
            twosame += diff * (i == j) * 2 + same * (i != j);
            allsame += same * (i == j);

            // cerr << i << ' ' << j << ' ' << res.num[0] << ' ' << (negate_hash[hsh] - (nh[i] == hsh) - (i != j && nh[j] == hsh)) * (i == j ? 1 : 2) << endl;

            // ans += (negate_hash[hsh] - (nh[i] == hsh) - (nh[j] == hsh)) * (i == j ? 1 : 2);
            // int pz = negate_hash[hsh] - (nh[i] == hsh) - (i != j && nh[j] == hsh);
            // cerr << i << ' ' << j << ' ' << pz << endl;
            // ans += (i == j) ? pz * 2 : pz;
        }
    }
    // cerr << alldiff << ' ' << twosame << ' ' << allsame << endl;
    cout << alldiff / 6 + twosame / 6 + allsame << endl;
}

int main(){
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    precomp();
    solve();
    return 0;
}

详细

Test #1:

score: 100
Accepted
time: 1ms
memory: 3668kb

input:

4 1
0
1
10
17

output:

3

result:

ok 1 number(s): "3"

Test #2:

score: -100
Time Limit Exceeded

input:

500 859
7118711592236878297922359501613604144948355616986970837340677671376753603836852811886591300370143151943368529129749813118476151865844255212534355441611481420938483178075143062691345257288242460282715389758789648541099090735875617822348551942134616963557723055980260082230902505269975518146286...

output:


result: