-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
3 changed files
with
344 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
/* #pragma GCC optimize("O3,unroll-loops") */ | ||
/* #pragma GCC optimize("Ofast,unroll-loops") */ | ||
/* #pragma GCC target("avx2,popcnt") */ | ||
#include <bits/stdc++.h> | ||
#include <ext/pb_ds/assoc_container.hpp> | ||
#include <ext/pb_ds/tree_policy.hpp> | ||
#define pb push_back | ||
#define mp make_pair | ||
#define all(a) begin(a),end(a) | ||
#define FOR(x,val,to) for(int x=(val);x<int((to));++x) | ||
#define FORE(x,val,to) for(auto x=(val);x<=(to);++x) | ||
#define FORR(x,arr) for(auto &x: arr) | ||
#define FORS(x,plus,arr) for(auto x = begin(arr)+(plus); x != end(arr); ++x) | ||
#define FORREV(x,plus,arr) for(auto x = (arr).rbegin()+(plus); x !=(arr).rend(); ++x) | ||
#define REE(s_) {cout<<s_<<'\n';exit(0);} | ||
#define GET(arr) for(auto &i: (arr)) sc(i) | ||
#define whatis(x) cerr << #x << " is " << (x) << endl; | ||
#define e1 first | ||
#define e2 second | ||
#define INF 0x7f7f7f7f | ||
typedef std::pair<int,int> pi; | ||
typedef std::vector<int> vi; | ||
typedef std::vector<std::string> vs; | ||
typedef int64_t ll; | ||
typedef uint64_t ull; | ||
#define umap unordered_map | ||
#define uset unordered_set | ||
using namespace std; | ||
using namespace __gnu_pbds; | ||
|
||
#ifdef ONLINE_JUDGE | ||
#define whatis(x) ; | ||
#endif | ||
#ifdef _WIN32 | ||
#define getchar_unlocked() _getchar_nolock() | ||
#define _CRT_DISABLE_PERFCRIT_LOCKS | ||
#endif | ||
template<class L, class R> ostream& operator<<(ostream &os, pair<L, R> P) { os<<"("<<P.first<<","<<P.second<<")"; return os; } | ||
template<class L, class R> ostream& operator<<(ostream &os, map<L, R> P) { for(auto const &vv: P)os<<"("<<vv.first<<","<<vv.second<<")"; return os; } | ||
template<class T> ostream& operator<<(ostream &os, set<T> V) { os<<"[";for(auto const &vv:V)os<<vv<<","; os<<"]"; return os; } | ||
template<class T> ostream& operator<<(ostream &os, vector<T> V) { os<<"[";for(auto const &vv:V)os<<vv<<","; os<<"]"; return os; } | ||
inline int fstoi(const string &str){auto it=str.begin();bool neg=0;int num=0;if(*it=='-')neg=1;else num=*it-'0';++it;while(it<str.end()) num=num*10+(*it++-'0');if(neg)num*=-1;return num;} | ||
inline void getch(char &x){while(x = getchar_unlocked(), x < 33){;}} | ||
inline void getstr(string &str){str.clear(); char cur;while(cur=getchar_unlocked(),cur<33){;}while(cur>32){str+=cur;cur=getchar_unlocked();}} | ||
template<typename T> inline bool sc(T &num){ bool neg=0; int c; num=0; while(c=getchar_unlocked(),c<33){if(c == EOF) return false;} if(c=='-'){ neg=1; c=getchar_unlocked(); } for(;c>47;c=getchar_unlocked()) num=num*10+c-48; if(neg) num*=-1; return true;}template<typename T, typename ...Args> inline void sc(T &num, Args &...args){ bool neg=0; int c; num=0; while(c=getchar_unlocked(),c<33){;} if(c=='-'){ neg=1; c=getchar_unlocked(); } for(;c>47;c=getchar_unlocked()) num=num*10+c-48; if(neg) num*=-1; sc(args...); } | ||
template<typename T> using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>; //s.find_by_order(), s.order_of_key() <- works like lower_bound | ||
template<typename T> using ordered_map = tree<T, int, less<T>, rb_tree_tag, tree_order_statistics_node_update>; | ||
#define debug(x...) cerr << "[" #x "]: ", [](auto... $) {((cerr << $ << "; "), ...); }(x), cerr << '\n' | ||
#define N 1000001 | ||
|
||
// Thx Jakub Radoszewski and Your Algorytmy Tekstowe | ||
|
||
bool equiv(string x, string y){ | ||
// x = uu; y = vv; | ||
int n = x.size(); // |u| == |v| | ||
x += x; | ||
y += y; | ||
int i = 0, j = 0; | ||
while (i<n and j<n){ | ||
int k = 0; | ||
while (k<n and x[i+k]==y[j+k]) ++k; | ||
if (k==n) return true; | ||
if (x[i+k]>y[j+k]) i += k+1; else j += k+1; | ||
} | ||
return false; | ||
} | ||
|
||
int main(){ | ||
ios_base::sync_with_stdio(0);cin.tie(0); | ||
whatis(equiv("abaababa", "babaabaa")) | ||
} | ||
|
83 changes: 83 additions & 0 deletions
83
up_to_3_triangular_number_np1choice2_sum_decomposition.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
/* #pragma GCC optimize("O3,unroll-loops") */ | ||
/* #pragma GCC optimize("Ofast,unroll-loops") */ | ||
/* #pragma GCC target("avx2,popcnt") */ | ||
#include <bits/stdc++.h> | ||
#include <ext/pb_ds/assoc_container.hpp> | ||
#include <ext/pb_ds/tree_policy.hpp> | ||
#define pb push_back | ||
#define mp make_pair | ||
#define all(a) begin(a),end(a) | ||
#define FOR(x,val,to) for(int x=(val);x<int((to));++x) | ||
#define FORE(x,val,to) for(auto x=(val);x<=(to);++x) | ||
#define FORR(x,arr) for(auto &x: arr) | ||
#define FORS(x,plus,arr) for(auto x = begin(arr)+(plus); x != end(arr); ++x) | ||
#define FORREV(x,plus,arr) for(auto x = (arr).rbegin()+(plus); x !=(arr).rend(); ++x) | ||
#define REE(s_) {cout<<s_<<'\n';exit(0);} | ||
#define GET(arr) for(auto &i: (arr)) sc(i) | ||
#define whatis(x) cerr << #x << " is " << (x) << endl; | ||
#define debug(x...) cerr << "[" #x "]: ", [](auto... $) {((cerr << $ << "; "), ...); }(x), cerr << '\n' | ||
#define e1 first | ||
#define e2 second | ||
#define INF 0x7f7f7f7f | ||
typedef std::pair<int,int> pi; | ||
typedef std::vector<int> vi; | ||
typedef std::vector<std::string> vs; | ||
typedef int64_t ll; | ||
typedef uint64_t ull; | ||
#define umap unordered_map | ||
#define uset unordered_set | ||
using namespace std; | ||
using namespace __gnu_pbds; | ||
|
||
#ifdef ONLINE_JUDGE | ||
#define whatis(x) ; | ||
#define debug(x) ; | ||
#endif | ||
#ifdef _WIN32 | ||
#define getchar_unlocked() _getchar_nolock() | ||
#define _CRT_DISABLE_PERFCRIT_LOCKS | ||
#endif | ||
template<class A, class B> auto& operator<<(ostream &o, pair<A, B> p) { return o << '(' << p.first << ", " << p.second << ')'; } | ||
template<class T, enable_if_t<!is_same<T, string>::value, bool> = true> auto operator<<(ostream &o, T x) -> decltype(x.end(), o) { o << '{'; int i = 0; for(auto e : x) o << (", ")+2*!i++ << e; return o << '}'; } | ||
inline void getch(char &x){while(x = getchar_unlocked(), x < 33){;}} | ||
inline void getstr(string &str){str.clear(); char cur;while(cur=getchar_unlocked(),cur<33){;}while(cur>32){str+=cur;cur=getchar_unlocked();}} | ||
template<typename T> inline bool sc(T &num){ bool neg=0; int c; num=0; while(c=getchar_unlocked(),c<33){if(c == EOF) return false;} if(c=='-'){ neg=1; c=getchar_unlocked(); } for(;c>47;c=getchar_unlocked()) num=num*10+c-48; if(neg) num*=-1; return true;}template<typename T, typename ...Args> inline void sc(T &num, Args &...args){ bool neg=0; int c; num=0; while(c=getchar_unlocked(),c<33){;} if(c=='-'){ neg=1; c=getchar_unlocked(); } for(;c>47;c=getchar_unlocked()) num=num*10+c-48; if(neg) num*=-1; sc(args...); } | ||
template<typename T> using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>; //s.find_by_order(), s.order_of_key() <- works like lower_bound | ||
template<typename T> using ordered_map = tree<T, int, less<T>, rb_tree_tag, tree_order_statistics_node_update>; | ||
#define N 1000001 | ||
|
||
// O(n) (+removable logn tutaj), iterating over the first 2 triangular numbers and then calculating the third. | ||
// https://en.wikipedia.org/wiki/Fermat_polygonal_number_theorem | ||
// n(n+1)/2; zwracane n in that. | ||
vector<int> decomp(int n){ | ||
vector<int> triang; | ||
for(int i = 1, sum = 1; sum <= n; sum += ++i){ | ||
if(sum == n) | ||
return {i}; | ||
triang.push_back(sum); | ||
} | ||
for(int i = 1, sum = 1; sum <= n; sum += ++i){ | ||
for(int x = 1, sum2 = 1; sum + sum2 <= n; sum2 += ++x){ | ||
int sum3 = n - sum - sum2; | ||
if(sum3 == 0) | ||
return {i, x}; | ||
if(binary_search(all(triang), sum3)) | ||
return {i, x, (int)(lower_bound(all(triang), sum3) - triang.begin() + 1)}; | ||
} | ||
} | ||
assert(0); | ||
} | ||
|
||
int main(){ | ||
ios_base::sync_with_stdio(0);cin.tie(0); | ||
FOR(i,1,2321313){ | ||
auto xd = decomp(i); | ||
int s = 0; | ||
FORR(i,xd){ | ||
s += i*(i+1)/2; | ||
} | ||
debug(i, xd); | ||
assert(s == i); | ||
} | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,189 @@ | ||
#pragma GCC optimize("O3,unroll-loops") | ||
#pragma GCC target("avx2,popcnt,fma") | ||
#include <bits/stdc++.h> | ||
using namespace std; | ||
using LL = long long; | ||
#define FOR(i, l, r) for(int i = (l); i <= (r); ++i) | ||
#define REP(i, n) FOR(i, 0, (n) - 1) | ||
#define ssize(x) int(x.size()) | ||
template<class A, class B> auto& operator<<(ostream &o, pair<A, B> p) { | ||
return o << '(' << p.first << ", " << p.second << ')'; | ||
} | ||
template<class T> auto operator<<(ostream &o, T x) -> decltype(x.end(), o) { | ||
o << '{'; int i = 0; for(auto e : x) o << (", ")+2*!i++ << e; return o << '}'; | ||
} | ||
ostream& operator<<(ostream &o, string &s) { | ||
return o << s.data(); | ||
} | ||
#ifdef DEBUG | ||
/* #ifdef LOCAL */ | ||
#define debug(x...) cerr << "[" #x "]: ", [](auto... $) {((cerr << $ << "; "), ...); }(x), cerr << '\n' | ||
#else | ||
#define debug(...) {} | ||
#endif | ||
// https://codeforces.com/gym/102835/problem/D | ||
|
||
int main(){ | ||
cin.tie(0)->sync_with_stdio(0); | ||
int n, m; | ||
cin >> n >> m; | ||
if(n == 2){ | ||
cout << "1\n"; | ||
return 0; | ||
} | ||
/* set<int> adj[n]; */ | ||
/* set<int> adj[31000]; */ | ||
/* set<int> adj[31000]; */ | ||
vector<int> adj[31000]; | ||
REP(i,m){ | ||
int f,s; | ||
cin >> f >> s; | ||
/* adj[f].insert(s); */ | ||
/* adj[s].insert(f); */ | ||
adj[f].push_back(s); | ||
adj[s].push_back(f); | ||
} | ||
REP(i,n) | ||
sort(adj[i].begin(), adj[i].end()); | ||
constexpr int origk = 28; | ||
int k = 28; | ||
bool erasd[n]; | ||
memset(erasd,0,n); | ||
/* // na pałę liniowo this part, though could smarter. */ | ||
/* // Part 1. Wywalenie all z deg > k. */ | ||
bool cont = 1; | ||
for(;cont;){ | ||
cont = 0; | ||
for(int i = 0; i < n; ++i){ | ||
if(erasd[i]) | ||
continue; | ||
if(adj[i].size() > k){ | ||
if(k <= 0){ | ||
cout << "-1\n"; | ||
return 0; | ||
} | ||
for(auto &x: adj[i]) | ||
/* adj[x].erase(i); */ | ||
adj[x].erase(lower_bound(adj[x].begin(), adj[x].end(), i)); | ||
erasd[i] = 1; | ||
--k; | ||
cont = 1; | ||
break; | ||
} | ||
} | ||
} | ||
/* // Reguła 2. |E| > k^2 -> -1. */ | ||
vector<int> rem; | ||
int edgecnt = 0; | ||
for(int i = 0; i < n; ++i){ | ||
if(!erasd[i] && adj[i].size()){ | ||
rem.push_back(i); | ||
edgecnt += adj[i].size(); | ||
} | ||
} | ||
// wait, podwójnie policzony miałem xd. | ||
edgecnt >>= 1; | ||
if(edgecnt > k * k){ | ||
cout << "-1\n"; | ||
return 0; | ||
} | ||
static bool vis[31000]; | ||
/* bool vis[n]; */ | ||
/* memset(vis, 0, n); */ | ||
/* auto bt = [&](vector<int> rem, int k){ */ | ||
debug(rem); | ||
auto bt = [&](auto self, int depth){ | ||
int mxdeg = 0; | ||
int whnode = -1; | ||
for(auto &i: rem){ | ||
int crdeg = 0; | ||
for(auto &x: adj[i]){ // way slower with adj as a set here obv. | ||
// (202ms without a set, even though this still is quite dumb) | ||
// Radeoosh has same, but without kernelization. Ja mem TLE bez | ||
// kernelization | ||
crdeg += binary_search(rem.begin(), rem.end(), x); | ||
} | ||
if(crdeg > mxdeg){ | ||
mxdeg = crdeg; | ||
whnode = i; | ||
} | ||
} | ||
if(!~whnode) | ||
return 0; | ||
if(depth >= k) | ||
return 1; // 1 + depth > k, czyli i tak zle by wychodziło. Very important. That's the difference between tle and not tle. Gotta limit the depth as far as is needed. | ||
// Or just do not wyifowańsko tego xd. | ||
// XD, it's actually faster without this. | ||
/* if(mxdeg <= 2){ */ | ||
/* // Łatwo rozwiązać. Chainy (m == n - 1) -> n / 2 floor; Cykle (m == n) -> n / 2 ceil. -> m / 2 ceil. */ | ||
/* int add = 0; */ | ||
/* vector<int> cleanupvec; */ | ||
/* for(auto &i: rem){ */ | ||
/* int ilem = 0; */ | ||
/* auto d1 = [&](auto self, int v) -> void{ */ | ||
/* cleanupvec.push_back(v); */ | ||
/* /1* debug(v); *1/ */ | ||
/* vis[v] = 1; */ | ||
/* for(auto &i: adj[v]){ */ | ||
/* if(!binary_search(rem.begin(), rem.end(), i)) */ | ||
/* continue; */ | ||
/* ++ilem; // can't be pod !vis[i], no bo moze byc cycle; lepiej tak, i >>= 1 potem simply. */ | ||
/* if(!vis[i]){ */ | ||
/* /1* debug(v, i); *1/ */ | ||
/* /1* ++ilem; *1/ */ | ||
/* self(self, i); */ | ||
/* } */ | ||
/* } */ | ||
/* }; */ | ||
/* if(!vis[i]){ */ | ||
/* d1(d1, i); */ | ||
/* debug(i, ilem); */ | ||
/* ilem >>= 1; */ | ||
/* add += (ilem + 1) >> 1; */ | ||
/* } */ | ||
/* } */ | ||
/* for(auto &i: cleanupvec) */ | ||
/* vis[i] ^= 1; */ | ||
/* /1* for(auto &i: rem){ *1/ */ | ||
/* /1* auto d2 = [&](auto self, int v) -> void{ *1/ */ | ||
/* /1* vis[v] = 0; *1/ */ | ||
/* /1* for(auto &i: adj[v]){ *1/ */ | ||
/* /1* if(!binary_search(rem.begin(), rem.end(), i)) *1/ */ | ||
/* /1* continue; *1/ */ | ||
/* /1* if(vis[i]){ *1/ */ | ||
/* /1* self(self, i); *1/ */ | ||
/* /1* } *1/ */ | ||
/* /1* } *1/ */ | ||
/* /1* }; *1/ */ | ||
/* /1* if(vis[i]){ *1/ */ | ||
/* /1* d2(d2, i); *1/ */ | ||
/* /1* } *1/ */ | ||
/* /1* } *1/ */ | ||
/* debug(rem, add); */ | ||
/* return add; */ | ||
/* } */ | ||
vector<int> origrem = rem; | ||
rem.erase(lower_bound(rem.begin(), rem.end(), whnode)); | ||
int wh = 1 + self(self, depth + 1); // dodajemy whnode do vertex cover. | ||
/* rem.insert(lower_bound(rem.begin(), rem.end(), whnode), whnode); */ | ||
// don't have to reinsert this one actually. | ||
for(auto &i: adj[whnode]){ | ||
if(binary_search(rem.begin(), rem.end(), i)){ | ||
rem.erase(lower_bound(rem.begin(), rem.end(), i)); | ||
} | ||
} | ||
wh = min(wh, mxdeg + self(self, depth + mxdeg)); // dodajemy adj(whnode) do vertex cover. | ||
rem = origrem; | ||
return wh; | ||
}; | ||
int ret = bt(bt, 0); | ||
if(ret <= k){ | ||
k -= ret; | ||
// max dopełnienie vertex coveru. | ||
cout << n - (origk - k) << '\n'; | ||
} | ||
else{ | ||
cout << "-1\n"; | ||
} | ||
} | ||
|