已经不知道是第几次因为代码常数大被卡掉了。
但是我不明白我的代码的常数总是很大,我自我感觉我打的很多代码也不算很丑/lh
问一个实际一点的问题吧,下面是我今天的 NOIP 模拟赛的一道题的代码,后面一段是我的一个同学的代码,我认为我实现得是比他精细的,实际上我 T 了但他没有,有没有好心人指出我的代码哪里常数过大了?
我的代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
unsigned long long rp;
ll ans, sum, x, tmp, lsh[500005];
int n, m, cnt[500005], r[61][500005], R[500005][61];
unordered_map<ll, int> id;
int main() {
#ifdef Lopera
freopen("game/ex_game3.in", "r", stdin);
// freopen("game.out", "w", stdout);
// freopen("game.err", "w", stderr);
#else
freopen("game.in", "r", stdin);
freopen("game.out", "w", stdout);
#endif
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
cin >> rp;
while(rp--) {
cin >> n;
m = 0;
id.clear();
for(int i = 1; i <= n; ++i) {
cin >> x;
if(!id.count(x)) {
id[x] = m;
lsh[m] = x, cnt[m] = 1;
++m;
}
else ++cnt[id[x]];
}
for(int j = 0; j < 61; ++j) {
id.clear();
x = 0;
for(int i = 0; i < m; ++i) {
tmp = (lsh[i] & ((1ll << j) - 1));
if(!id.count(tmp)) r[j][id[tmp] = x++] = 0;
r[j][R[i][j] = id[tmp]] += cnt[i];
}
}
ans = n * (n - 1ll) * (n - 2ll) / 6;
for(int i = 0; i < m; ++i) {
if(cnt[i] == 1) continue;
sum = -cnt[i];
for(int j = 0; j < 61; ++j) {
if(j & 1) sum -= r[j][R[i][j]];
else sum += r[j][R[i][j]];
}
ans -= cnt[i] * (cnt[i] - 1ll) * (cnt[i] - 2ll) / 6ll + cnt[i] * (cnt[i] - 1ll) / 2ll * sum;
}
cout << ans << '\n';
}
cerr << (double)clock() / CLOCKS_PER_SEC;
return 0;
}
我同学的代码
#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
const ll IINF = 1e18;
const int N = 5e5 + 5, M = 2e7 + 5;
int flg[105][105][105];
int sg(int i, int j, int k) {
int a[3] = {i, j, k};
sort(a, a + 3);
i = a[0], j = a[1], k = a[2];
if(flg[i][j][k] != -1) return flg[i][j][k];
set<int> f;
for(int l = 1; l <= (j - i) / 2; l++) f.insert(sg(i + l, j - l, k));
for(int l = 1; l <= (k - i) / 2; l++) f.insert(sg(i + l, j, k - l));
for(int l = 1; l <= (k - j) / 2; l++) f.insert(sg(i, j + l, k - l));
for(int l = 0; ; l++) if(!f.count(l)) return flg[i][j][k] = l;
}
void baoli() {
memset(flg, -1, sizeof flg);
for(int i = 1; i <= 10; i++) for(int j = i + 1; j <= 10; j++) for(int k = j + 1; k <= 10; k++) {
if(!sg(i, j, k)) printf("%d %d %d\n", i, j, k);
}
}
int n, T, cnt;
ll a[N], lsh[N], ans;
unordered_map<ll, int> mp;
int tr[M][2], vis[M][2], siz[M];
void insert(ll x) {
int p = 0;
for(int i = 0; i <= 60; i++) {
int opt = (x >> i) & 1;
if(vis[p][opt] != T) vis[p][opt] = T, tr[p][opt] = ++cnt, siz[cnt] = 0;
siz[p = tr[p][opt]]++;
}
}
void query(ll x, ll res) {
int p = 0, fa = 0;
for(int i = 0; i <= 60; i++) {
int opt = (x >> i) & 1;
if(vis[p][opt] != T) vis[p][opt] = T, tr[p][opt] = 0;
if(vis[p][1 - opt] != T) vis[p][1 - opt] = T, tr[p][1 - opt] = 0;
if((i & 1)) ans += res * siz[tr[fa][1 - ((x >> i - 1) & 1)]];
fa = p, p = tr[p][opt];
}
ans += 1ll * siz[p] * (siz[p] - 1) / 2 * (siz[p] - 2) / 3;
}
void solve() {
ans = cnt = 0, T++;
cin>>n;
for(int i = 1; i <= n; i++) cin>>a[i], insert(a[i]);
sort(a + 1, a + n + 1);
a[n + 1] = -1;
for(int i = 1, lst = 1; i <= n; i++) if(a[i] != a[i + 1]) {
ll tmp = i - lst + 1;
query(a[i], tmp * (tmp - 1) / 2);
lst = i + 1;
}
cout<<1ll * n * (n - 1) / 2 * (n - 2) / 3 - ans<<'\n';
}
int main() {
cnt = 0;
freopen("game.in", "r", stdin);
freopen("game.out", "w", stdout);
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
int t; cin>>t;
while(t--) solve();
cerr<<clock() * 1.0 / CLOCKS_PER_SEC<<'\n';
return 0;
}