QOJ.ac
QOJ
ID | 题目 | 提交者 | 结果 | 用时 | 内存 | 语言 | 文件大小 | 提交时间 | 测评时间 |
---|---|---|---|---|---|---|---|---|---|
#349010 | #8340. 3 Sum | ucup-team197# | TL | 265ms | 8124kb | C++20 | 8.0kb | 2024-03-09 23:01:40 | 2024-03-09 23:01:41 |
Judging History
answer
#pragma GCC optimize("Ofast,unroll-loops,no-stack-protector,fast-math,inline")
// #pragma GCC target("avx2")
#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];
// // vector<ll> num;
inline void add(ll a[], ll b[], ll res[]) {
int carry = 0;
for(int i = 0; i < S; i++) {
res[i] = carry + a[i] + b[i];
carry = 0;
if(res[i] >= M) {
res[i] -= M;
carry = 1;
}
}
}
inline void resolve_carry(ll num[], int carry) {
for(int i = 0; i < S; i++) {
if(carry == 0) {
return;
}
num[i] += carry;
carry = 0;
if(num[i] >= M) {
num[i] -= M;
carry = 1;
}
}
}
inline void norm(ll num[], 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, S * sizeof(int));
}
inline void inegate(ll num[], ll res[], int k) {
memset(res, 0, S * sizeof(int));
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[i] = limit - 1 - num[i];
}
norm(res, k);
}
// inline void plusmod(ll a[], ll b[], ll res[], int k) {
// add(a, b, c);
// c.norm(k);
// return c;
// }
inline void add_digit(ll num[], int d, int pos, int k, int &spill) {
int big = pos / D;
int idx = pos % D;
num[big] += pow10[idx] * d;
for(int i = big; i < S; i++) {
if(i * D > k) break;
ll limit = M;
bool end = (i+1) * D > k;
if(end) [[unlikely]]{
limit = pow10[k - i * D];
}
if(num[i] >= limit) [[likely]] {
if(end) {
num[i] -= limit;
spill++;
} else {
num[i] -= M;
num[i+1]++;
}
} else {
break;
}
}
}
ll ihash(ll num[]) {
ll result = 0;
for(int i = 0; i+4 < S; i+=4) {
result = (result + rnd[i] * num[i] + rnd[i+1] * num[i+1] + rnd[i+2] * num[i+2] + rnd[i+3] * num[i+3]) % MOD;
}
return result;
}
// };
const int N = 500;
ll nums[N][S];
ll lim[S];
ll neg[S];
ll neg2[S];
ll res[S];
void solve(){
int n;
int k;
cin >> n >> k;
memset(nums, 0, sizeof(nums));
// vector<BigInt> nums;
for(int i = 0; i < n; i++) {
// cerr << i << endl;
string s;
cin >> s;
reverse(s.begin(), s.end());
int len = s.size();
// BigInt t;
// memset(nums[i], 0, sizeof(nums[i]));
vi carry(S);
int spill = 0;
for(int j = 0; j < len; j++) {
// cerr << i << endl;
// t.add_digit(s[i]-'0', i % k, k, spill);
add_digit(nums[i], s[j]-'0', j % k, k, spill);
// cerr << nums[i][0] << endl;
// 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;
resolve_carry(nums[i], spill);
norm(nums[i], k);
}
memset(lim, 0, sizeof(lim));
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];
}
lim[i] = limit - 1;
}
// for(int i = 0; i < min(10, n); i++) {
// for(int j = 0; j < 4; j++) {
// cout << nums[i][j] << ' ';
// }
// cout << endl;
// }
vll nh;
vll nh2;
map<ll, int> negate_hash;
for(int i = 0; i < n; i++) {
// BigInt neg = inegate(nums[i], k);
inegate(nums[i], neg, k);
// cerr << neg[0] << endl;
ll h = ihash(neg);
add(neg, lim, neg2);
ll h2 = ihash(neg2);
nh.push_back(h);
nh2.push_back(h2);
negate_hash[h]++;
negate_hash[h2]++;
}
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++) {
// cerr << i << ' ' << j << endl;
// BigInt res = plusmod(nums[i], nums[j], k);
// BigInt res = nums[i] + nums[j];
add(nums[i], nums[j], res);
ll hsh = ihash(res);
// cerr << "hsh " << hsh << endl;
// ll hsh = rng() % 10;
int tot = 0;
if(negate_hash.find(hsh) != negate_hash.end()) {
tot = negate_hash[hsh];
}
int same = (nh[i] == hsh || nh2[i] == hsh) + ( (nh[j] == hsh || nh2[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: 0ms
memory: 8084kb
input:
4 1 0 1 10 17
output:
3
result:
ok 1 number(s): "3"
Test #2:
score: 0
Accepted
time: 265ms
memory: 8124kb
input:
500 859 7118711592236878297922359501613604144948355616986970837340677671376753603836852811886591300370143151943368529129749813118476151865844255212534355441611481420938483178075143062691345257288242460282715389758789648541099090735875617822348551942134616963557723055980260082230902505269975518146286...
output:
0
result:
ok 1 number(s): "0"
Test #3:
score: -100
Time Limit Exceeded
input:
500 17336 11871159223687829792235950161360414494835561698697083734067767137675360383685281188659130037014315194336852912974981311847615186584425521253435544161148142093848317807514306269134525728824246028271538975878964854109909073587561782234855194213461696355772305598026008223090250526997551814628...