QOJ.ac
QOJ
ID | 题目 | 提交者 | 结果 | 用时 | 内存 | 语言 | 文件大小 | 提交时间 | 测评时间 |
---|---|---|---|---|---|---|---|---|---|
#120137 | #6186. Cryptography Problem | hos_lyric | AC ✓ | 602ms | 3964kb | C++14 | 7.1kb | 2023-07-06 14:11:50 | 2023-07-06 14:11:53 |
Judging History
answer
#include <cassert>
#include <cmath>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <bitset>
#include <complex>
#include <deque>
#include <functional>
#include <iostream>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>
using namespace std;
using Int = long long;
template <class T1, class T2> ostream &operator<<(ostream &os, const pair<T1, T2> &a) { return os << "(" << a.first << ", " << a.second << ")"; };
template <class T> ostream &operator<<(ostream &os, const vector<T> &as) { const int sz = as.size(); os << "["; for (int i = 0; i < sz; ++i) { if (i >= 256) { os << ", ..."; break; } if (i > 0) { os << ", "; } os << as[i]; } return os << "]"; }
template <class T> void pv(T a, T b) { for (T i = a; i != b; ++i) cerr << *i << " "; cerr << endl; }
template <class T> bool chmin(T &t, const T &f) { if (t > f) { t = f; return true; } return false; }
template <class T> bool chmax(T &t, const T &f) { if (t < f) { t = f; return true; } return false; }
////////////////////////////////////////////////////////////////////////////////
struct ModLong {
static unsigned long long M;
static long double INV_M;
static void setM(unsigned long long m) { M = m; INV_M = 1.0L / M; }
unsigned long long x;
ModLong() : x(0ULL) {}
ModLong(unsigned x_) : x(x_ % M) {}
ModLong(unsigned long long x_) : x(x_ % M) {}
ModLong(int x_) : x(((x_ %= static_cast<long long>(M)) < 0) ? (x_ + static_cast<long long>(M)) : x_) {}
ModLong(long long x_) : x(((x_ %= static_cast<long long>(M)) < 0) ? (x_ + static_cast<long long>(M)) : x_) {}
ModLong &operator+=(const ModLong &a) { x = ((x += a.x) >= M) ? (x - M) : x; return *this; }
ModLong &operator-=(const ModLong &a) { x = ((x -= a.x) >= M) ? (x + M) : x; return *this; }
ModLong &operator*=(const ModLong &a) {
// https://github.com/kth-competitive-programming/kactl/blob/main/doc/modmul-proof.pdf
// This works at least for M < 2^62, assuming the usual 80-bit long double.
const long long y = x * a.x - M * static_cast<unsigned long long>(INV_M * x * a.x);
x = (y < 0LL) ? (y + M) : (y >= static_cast<long long>(M)) ? (y - M) : y;
return *this;
}
ModLong &operator/=(const ModLong &a) { return (*this *= a.inv()); }
ModLong pow(long long e) const {
if (e < 0) return inv().pow(-e);
ModLong a = *this, b = 1ULL; for (; e; e >>= 1) { if (e & 1) b *= a; a *= a; } return b;
}
ModLong inv() const {
unsigned long long a = M, b = x; long long y = 0, z = 1;
for (; b; ) { const unsigned long long q = a / b; const unsigned long long c = a - q * b; a = b; b = c; const long long w = y - static_cast<long long>(q) * z; y = z; z = w; }
assert(a == 1ULL); return ModLong(y);
}
ModLong operator+() const { return *this; }
ModLong operator-() const { ModLong a; a.x = x ? (M - x) : 0ULL; return a; }
ModLong operator+(const ModLong &a) const { return (ModLong(*this) += a); }
ModLong operator-(const ModLong &a) const { return (ModLong(*this) -= a); }
ModLong operator*(const ModLong &a) const { return (ModLong(*this) *= a); }
ModLong operator/(const ModLong &a) const { return (ModLong(*this) /= a); }
template <class T> friend ModLong operator+(T a, const ModLong &b) { return (ModLong(a) += b); }
template <class T> friend ModLong operator-(T a, const ModLong &b) { return (ModLong(a) -= b); }
template <class T> friend ModLong operator*(T a, const ModLong &b) { return (ModLong(a) *= b); }
template <class T> friend ModLong operator/(T a, const ModLong &b) { return (ModLong(a) /= b); }
explicit operator bool() const { return x; }
bool operator==(const ModLong &a) const { return (x == a.x); }
bool operator!=(const ModLong &a) const { return (x != a.x); }
friend std::ostream &operator<<(std::ostream &os, const ModLong &a) { return os << a.x; }
};
unsigned long long ModLong::M;
long double ModLong::INV_M;
////////////////////////////////////////////////////////////////////////////////
using Mint = ModLong;
using INT = __int128;
INT divFloor(INT a, INT b) {
return a / b - (((a ^ b) < 0 && a % b != 0) ? 1 : 0);
}
INT divCeil(INT a, INT b) {
return a / b + (((a ^ b) > 0 && a % b != 0) ? 1 : 0);
}
constexpr int H = 6;
constexpr int NUM_CANDS = 500;
constexpr int WIDTH = 10;
int M;
Int P;
vector<Mint> A, C;
Int maxErr;
bool check(Mint x) {
for (int i = 0; i < M; ++i) {
const Mint e = C[i] - A[i] * x;
if (!((Int)e.x <= maxErr || P - maxErr <= (Int)e.x)) {
return false;
}
}
return true;
}
int main() {
for (int numCases; ~scanf("%d", &numCases); ) { for (int caseId = 1; caseId <= numCases; ++caseId) {
scanf("%d%lld", &M, &P);
Mint::setM(P);
A.resize(M);
C.resize(M);
for (int i = 0; i < M; ++i) {
scanf("%llu%llu", &A[i].x, &C[i].x);
}
maxErr = P / 200;
vector<pair<Mint, Mint>> acss[H + 1];
for (int i = 0; i < M; ++i) {
acss[0].emplace_back(A[i], C[i]);
}
for (int h = 0; ; ++h) {
sort(acss[h].begin(), acss[h].end(), [&](const pair<Mint, Mint> &ac0, const pair<Mint, Mint> &ac1) -> bool {
return (ac0.first.x < ac1.first.x);
});
acss[h].erase(unique(acss[h].begin(), acss[h].end()), acss[h].end());
if ((int)acss[h].size() > NUM_CANDS) {
acss[h].resize(NUM_CANDS);
}
// cerr<<"acss["<<h<<"] = ";for(int i=0;i<10;++i)cerr<<acss[h][i]<<" ";cerr<<"..."<<endl;
if (h == H) {
break;
}
for (int i = 0; i < (int)acss[h].size(); ++i) {
for (int j = i + 1; j < (int)acss[h].size() && j < i + WIDTH; ++j) {
const Mint ai = acss[h][i].first;
const Mint ci = acss[h][i].second;
const Mint aj = acss[h][j].first;
const Mint cj = acss[h][j].second;
if (ai != aj) {
acss[h + 1].emplace_back(aj - ai, cj - ci);
}
}
}
}
// possible intervals for y
vector<pair<Int, Int>> fs;
fs.emplace_back(0, P - 1);
for (int h = H; h >= 0; --h) {
const INT err = maxErr << h;
for (const auto &ac : acss[h]) {
const INT a = ac.first.x;
const INT c = ac.second.x;
vector<pair<Int, Int>> gs;
for (const auto &f : fs) {
const INT lb = a * f.first - err;
const INT ub = a * f.second + err;
for (INT cc = c + P * divCeil(lb - c, P); cc <= ub; cc += P) {
Int mn = divCeil(cc - err, a);
Int mx = divFloor(cc + err, a);
chmax(mn, f.first);
chmin(mx, f.second);
if (mn <= mx) {
gs.emplace_back(mn, mx);
}
}
}
fs.swap(gs);
}
// cerr<<"fs = "<<fs<<endl;
}
assert((int)fs.size() == 1);
assert(fs[0].first == fs[0].second);
const Mint x = fs[0].first;
assert(check(x));
printf("%llu\n", x.x);
}
#ifndef LOCAL
break;
#endif
}
return 0;
}
详细
Test #1:
score: 100
Accepted
time: 1ms
memory: 3828kb
input:
1 50 922033901407246477 492300877907148697 8585039545574817 36478175140515505 237143454432095134 537753813197233578 694568987600933631 82789600405017625 562554784008054548 282428338659751664 111810756866364131 822189940492446170 74373256662670811 772047021157436862 845822103589054835 905076737759700...
output:
578607642570710976
result:
ok 1 number(s): "578607642570710976"
Test #2:
score: 0
Accepted
time: 60ms
memory: 3964kb
input:
50 50 927676989640655977 762098094289388675 554350133173402673 220848340400099833 10383368447694956 193839768013701504 379314325246244053 469365359426047896 616262947838432737 678500220535707545 834311280111269471 167419353273448183 166399514139956977 328321928151136515 281838830155886019 7710446445...
output:
254386793227895013 503373249026109683 617255058572731111 468676128207905624 504667964722475709 706980297728347748 654692631554025788 717119724503084980 48846540328002409 457755605535919837 731004188713847898 881500317550344403 265866468225776627 700114442334748277 772736562662367547 4770957264032135...
result:
ok 50 numbers
Test #3:
score: 0
Accepted
time: 590ms
memory: 3956kb
input:
500 50 951821513919240751 781258612744948669 555654292257394605 413029409925362472 528677554280211238 642254341504063583 252890250480181779 77913229002142898 852299116162342377 163586964773590385 301627013265727254 125813686708831709 851092599442448537 81859193591161149 292739685639200100 8004099527...
output:
322665687973068008 719744704337683378 223621712975394904 578842113669482761 579478401273129423 894615012983560279 55304797288242586 900547069473317102 841180533649876743 254296854628506468 165788977022011896 452665978765620390 893182474374282887 888765525028652186 165384334567641643 3096260905621286...
result:
ok 500 numbers
Test #4:
score: 0
Accepted
time: 585ms
memory: 3932kb
input:
500 50 918826966998423649 530004725701494083 461211593687456594 63103588668618552 819676939043626802 845224244943758942 735446711222510978 569183338186454323 884938560895198255 369490838717379648 333643655158879597 799092903635804915 458323668175155716 596200969807461760 751602048149560036 137459688...
output:
356039301456951045 735071103390342669 907633045757956007 80333220403160355 512654676652610218 853151271051375985 6900635554229793 319250522861749251 502089686656976731 706400239469090662 864293875669636701 184585628877202200 765153323638554684 402732305683171984 96578015632385890 33355119284189045 3...
result:
ok 500 numbers
Test #5:
score: 0
Accepted
time: 602ms
memory: 3920kb
input:
500 50 974253393840009889 594332492408784824 973795908768118711 374921723194021568 146694632264962823 158991793399209625 630100905073861940 386845674820240430 546167425238254176 583567998099720927 555458291915934761 662461153156085006 118223913225418273 170565109472431590 707652557260570730 77396204...
output:
721648842958392017 132349150866295563 932229954637440499 683889607900407446 691629840948421027 33025736080549009 495041676223202172 647589505742632734 186935292562953038 110626757212384825 685749428568030610 519425761135381806 758834050890676812 828787588813279594 232938032671135667 4540525995638170...
result:
ok 500 numbers