QOJ.ac
QOJ
ID | 题目 | 提交者 | 结果 | 用时 | 内存 | 语言 | 文件大小 | 提交时间 | 测评时间 |
---|---|---|---|---|---|---|---|---|---|
#294062 | #6186. Cryptography Problem | Radewoosh# | TL | 531ms | 16292kb | C++23 | 7.2kb | 2023-12-30 03:14:55 | 2023-12-30 03:14:56 |
Judging History
answer
//~ while (clock()<=69*CLOCKS_PER_SEC)
//~ #pragma comment(linker, "/stack:200000000")
#pragma GCC optimize("O3")
//~ #pragma GCC target ("avx2")
//~ #pragma GCC optimize("Ofast")
//~ #pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
//~ #pragma GCC optimize("unroll-loops")
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
using namespace std;
template <typename T>
using ordered_set =
tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;
#define sim template < class c
#define ris return * this
#define dor > debug & operator <<
#define eni(x) sim > typename \
enable_if<sizeof dud<c>(0) x 1, debug&>::type operator<<(c i) {
sim > struct rge { c b, e; };
sim > rge<c> range(c i, c j) { return rge<c>{i, j}; }
sim > auto dud(c* x) -> decltype(cerr << *x, 0);
sim > char dud(...);
struct debug {
#ifdef LOCAL
~debug() { cerr << endl; }
eni(!=) cerr << boolalpha << i; ris; }
eni(==) ris << range(begin(i), end(i)); }
sim, class b dor(pair < b, c > d) {
ris << "(" << d.first << ", " << d.second << ")";
}
sim dor(rge<c> d) {
*this << "[";
for (auto it = d.b; it != d.e; ++it)
*this << ", " + 2 * (it == d.b) << *it;
ris << "]";
}
#else
sim dor(const c&) { ris; }
#endif
};
#define imie(...) " [" << #__VA_ARGS__ ": " << (__VA_ARGS__) << "] "
#define shandom_ruffle random_shuffle
using ll=long long;
using pii=pair<int,int>;
using pll=pair<ll,ll>;
using vi=vector<int>;
using vll=vector<ll>;
const int nax=5000*1007;
using ld=long double;
int n;
ll p;
ll o2;
pll tab[nax];
pll normuj(pll v)
{
while(v.first<0)
{
v.first+=p;
v.second+=p;
}
while(v.first>=p)
{
v.first-=p;
v.second-=p;
}
return v;
}
inline ll mno(ll a, ll b)
{
return (a*(__int128)b)%p;
}
ll pot(ll a, ll b)
{
ll ret=1;
while(b)
{
if (b&1)
ret=mno(ret, a);
a=mno(a, a);
b>>=1;
}
return ret;
}
ll inv(ll v)
{
return pot(v, p-2);
}
pll now[nax];
int nowr;
pll wek[nax];
int wekr;
vector<pair<ll,pll>> szuk(ll chce)
{
wekr=0;
ll ocel=inv(chce);
for (int i=1; i<=n; i++)
if (rand()%20)
wek[wekr++]={mno(tab[i].first, ocel), tab[i].second};
sort(wek, wek+wekr);
int d=5;
const int ogr=700;
int outuj=0;
for (int h=0; h<d; h++)
{
//~ if (wek[0].first<3000)
//~ {
//~ debug() << "faster " << h;
//~ d=h;
//~ break;
//~ }
nowr=0;
for (int h1=0; h1+1<wekr; h1++)
{
for (int h2=h1+1; h2<wekr && h2<=h1+7; h2++)
{
ll x=wek[h2].first-wek[h1].first;
ll y=wek[h2].second-wek[h1].second;
if (!x)
continue;
if (y<0)
y+=p;
if (x<1000)
{
wek[0]={x, y};
wekr=1;
outuj=1;
d=h+1;
break;
}
now[nowr++]={x, y};
}
if (outuj)
break;
}
if (outuj)
break;
if (nowr<ogr+50)
{
sort(now, now+nowr);
}
else
{
nth_element(now, now+ogr+20, now+nowr);
sort(now, now+ogr+20);
}
wekr=0;
for (int i=0; i<nowr && wekr<ogr && i<ogr+20; i++)
{
if (!i || now[i].first!=wek[wekr-1].first)
{
wek[wekr++]=now[i];
}
}
}
wekr=min(wekr, 1);
for (int i=wekr-1; i; i--)
if (wek[i].first*5>wek[0].first*4)
wekr--;
vector<pair<ll,pll>> ret;
for (int h=0; h<wekr; h++)
{
ll x=wek[h].first;
ll y=wek[h].second;
pll prz{y-((p/600)<<d), y+((p/600)<<d)};
ret.push_back({x, normuj(prz)});
}
return ret;
}
pll raz[nax];
int razr;
pll dwa[nax];
int dwar;
pll ret[nax];
int retr;
void przetnij()
{
sort(dwa, dwa+dwar);
if (razr==1 && raz[0].second-raz[0].first==p-1)
{
for (int i=0; i<dwar; i++)
raz[i]=dwa[i];
razr=dwar;
return;
}
retr=0;
int wskr=0;
int wskd=0;
while(wskr<razr && wskd<dwar)
{
pll x=raz[wskr];
pll y=dwa[wskd];
if (x.second<y.first)
{
wskr++;
continue;
}
if (y.second<x.first)
{
wskd++;
continue;
}
pll z={max(x.first, y.first), min(x.second, y.second)};
if (z.first<=z.second)
ret[retr++]=z;
if (x.second<y.second)
wskr++;
else
wskd++;
}
for (int i=0; i<retr; i++)
raz[i]=ret[i];
razr=retr;
}
void test()
{
scanf("%d%lld", &n, &p);
o2=(p+1)/2;
for (int i=1; i<=n; i++)
scanf("%lld%lld", &tab[i].first, &tab[i].second);
while(1)
{
razr=1;
raz[0]={0, p-1};
ll mnoznik=1;
while(1)
{
auto wezwsz=szuk(mnoznik);
if (wezwsz[0].first>=nax/10)
continue;
for (auto wez : wezwsz)
{
//~ spent-=get_time();
ll d=wez.first;
if (d>=nax/10)
continue;
ll o=inv(d);
ll a=wez.second.first;
ll b=wez.second.second;
dwar=0;
for (int h=0; h<d; h++)
{
ll x=a+h;
if (x>b)
break;
ll ile=(b-x)/d+1;
static ll g;
if (!h)
{
g=mno(x, o);
}
else
{
g+=o;
if (g>=p)
g-=p;
}
if (g+ile-1>p)
{
dwa[dwar++]={g, p-1};
dwa[dwar++]={0, g+ile-1-p};
}
else
{
dwa[dwar++]={g, g+ile-1};
}
}
//~ spent+=get_time();
przetnij();
}
ll dobre=0;
//~ for (pll i : raz)
for (int i=0; i<razr; i++)
dobre+=raz[i].second-raz[i].first+1;
if (dobre<=50000)
{
break;
}
//~ debug() << imie(dobre) << imie(dobre/(double)p) << imie(raz.size());
//~ debug() << mnoznik << " " << imie(dobre) << imie((raz.back().second-raz[0].first)/(double)p);
//~ if ((raz.back().second-raz[0].first)*3<p*2 && (int)raz.size()<=100)
const int lim=200;
if (dobre*2<p && razr<=lim/2)
//~ if ((int)raz.size()<=5000)
{
dwar=0;
const ll mnoze=max(lim/razr, 2);
//~ const ll mnoze=2+(rand()&1);
const ll oo=inv(mnoze);
mnoznik=mno(mnoznik, oo);
for (int hh=0; hh<razr; hh++)
{
pll i=raz[hh];
ll a=i.first;
ll b=i.second;
for (int h=0; h<mnoze; h++)
{
ll x=a+h;
if (x>b)
break;
ll ile=(b-x)/mnoze+1;
static ll g;
if (!h)
{
g=mno(x, oo);
}
else
{
g+=oo;
if (g>=p)
g-=p;
}
if (g+ile-1>p)
{
dwa[dwar++]={g, p-1};
dwa[dwar++]={0, g+ile-1-p};
}
else
{
dwa[dwar++]={g, g+ile-1};
}
}
}
sort(dwa, dwa+dwar);
for (int i=0; i<dwar; i++)
raz[i]=dwa[i];
razr=dwar;
}
}
ll pam=inv(mnoznik);
//~ printf("%lld\n", mno(raz[0].first, inv(mnoznik)));
for (int hh=0; hh<razr; hh++)
{
pll h=raz[hh];
for (ll x=h.first; x<=h.second; x++)
{
//~ ll w=mno(x, pam);
ll w=x*(__int128)pam%p;
int ok=1;
for (int i=1; i<=n; i++)
{
//~ ll y=mno(tab[i].first, w)-tab[i].second;
ll y=tab[i].first*(__int128)w%p;
y-=tab[i].second;
y%=p;
if (y<0)
y+=p;
if (y>p/2)
y-=p;
if (abs(y)>p/200)
{
ok=0;
break;
}
}
if (ok)
{
printf("%lld\n", w);
return;
}
}
}
debug() << "error";
}
}
int main()
{
srand(time(0));
int t;
scanf("%d", &t);
while(t--)
test();
return 0;
}
详细
Test #1:
score: 100
Accepted
time: 9ms
memory: 14180kb
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: 531ms
memory: 16292kb
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: -100
Time Limit Exceeded
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...