B.Boundary
给定一个二维平面,以及n个点,求一个过圆心的圆,问最多有多少个点在圆上。
思路:
枚举C (n,2) 个点 ,从而得到圆心。若在在一个圆上,必然圆心也是同一个,圆心同一个也必在圆上。
要注意,枚举一个循环就计算一次,否则两次再算要考虑容斥,太麻烦了。
#include<iostream> #include<algorithm> #include<bitset> //#include<unordered_map> #include<fstream> #include<iomanip> #include<string> #include<cmath> #include<cstring> #include<vector> #include<map> #include<set> #include<list> #include<queue> #include<stack> #include<sstream> #include<cstdio> #include<ctime> #include<cstdlib> #define INF 0x3f3f3f3f #define inf 0x7FFFFFFF #define MOD 1000000007 #define moD 1000000003 #define pii pair<int,int> #define eps 1e-8 #define equals(a,b) (fabs(a-b)<eps) #define bug puts("bug") #define re register #define fi first #define se second const int maxn = 1e5 + 5; const double Inf = 10000.0; const double PI = acos(-1.0); typedef long long ll; using namespace std; struct Point { double x, y; Point() { x = y = 0; } Point(double _x, double _y) { x = _x; y = _y; } }; bool operator < (const Point& a, const Point& b) { return a.x < b.x || (a.x == b.x && a.y < b.y); } Point get_o(Point a, Point b, Point c) { double x1 = a.x, y1 = a.y; double x2 = b.x, y2 = b.y; double x3 = c.x, y3 = c.y; double a1 = 2 * (x2 - x1); double b1 = 2 * (y2 - y1); double c1 = x2 * x2 + y2 * y2 - x1 * x1 - y1 * y1; double a2 = 2 * (x3 - x2); double b2 = 2 * (y3 - y2); double c2 = x3 * x3 + y3 * y3 - x2 * x2 - y2 * y2; double x = (c1 * b2 - c2 * b1) / (a1 * b2 - a2 * b1); double y = (a1 * c2 - a2 * c1) / (a1 * b2 - a2 * b1); return Point(x, y); } bool check(Point a, Point b, Point c) { if (equals((b.y - a.y) * (c.x - a.x), (c.y - a.y) * (b.x - a.x))) return 0; return 1; } bool eq(Point a, Point b) { return equals(a.x, b.x) && equals(a.y, b.y); } vector<Point> v; Point pp[maxn]; int main() { int n; scanf("%d", &n); double x, y; Point p (0,0); for (int i = 0; i < n; i++) { scanf("%lf%lf", &x, &y); pp[i].x = x, pp[i].y = y; } if (n <= 2) { printf("%d",n); return 0; } int Max = 1; for (int i = 0; i < n; i++) { v.clear(); for (int j = i + 1; j < n; j++) { if (check(p, pp[i], pp[j])) v.push_back(get_o(p, pp[i], pp[j])); } sort(v.begin(), v.end()); int cnt = 2; for (int i = 1; i < v.size(); i++) { if (eq(v[i - 1], v[i])) cnt++, Max = max(Max, cnt); else Max = max(Max, cnt), cnt = 2; } } printf("%d", Max); }
J . Just Shuffle
给出一个排列A,要求设计一个置换(可以理解成一种映射) 经过恰好 k 步 (K是一个大质数) 可从排列{1,2,3,,,n} 变为 A 。求这种置换经过一步后的结果。
需要前置知识 : 置换群,循环置换,置换求逆。
#pragma warning(disable:4996) #include<iostream> #include<algorithm> #include<bitset> //#include<unordered_map> #include<fstream> #include<iomanip> #include<string> #include<cmath> #include<cstring> #include<vector> #include<map> #include<set> #include<list> #include<queue> #include<stack> #include<sstream> #include<cstdio> #include<ctime> #include<cstdlib> #define INF 0x3f3f3f3f #define inf 0x7FFFFFFF #define MOD 1000000007 #define moD 1000000003 #define pii pair<int,int> #define eps 1e-8 #define equals(a,b) (fabs(a-b)<eps) #define bug puts("bug") #define re register #define fi first #define se second const int maxn = 1e5 + 5; const double Inf = 10000.0; const double PI = acos(-1.0); typedef long long ll; using namespace std; int a[maxn], b[maxn]; int vis[maxn]; ll exgcd(ll a, ll b, ll& x, ll& y) { if (b == 0) { x = 1; y = 0; return a; } ll g = exgcd(b, a % b, x, y); ll t = x; x = y; y = t - a / b * y; return g; } ll inv(ll a, ll n) { ll x, y; exgcd(a, n, x, y); return (x + n) % n; } int main() { int n, k; scanf("%d%d", &n, &k); for (int i = 0; i < n; i++) scanf("%d", a + i + 1); for (int i = 1; i <= n; i++) { if (vis[i]) continue; vector<int> v; for (int j = i; !vis[j]; j = a[j]) { vis[j] = 1; v.push_back(j); } int rr = v.size(); int r = k % rr; for (int j = 0; j < rr; j++) { b[v[j]] = v[(j + inv(r, rr)) % rr]; } } for (int i = 1; i < n; i++) printf("%d ", b[i]); printf("%d", b[n]); }
G
给两序列A,B。 求A中满足对应位置大于B对应位置的区间个数。
bitset套路题 对每个Bi 求一个bitset,若Aj大于Bi,则为1 。 最后只要对于Bi的bitset右移动i位,对所有Bi进行与操作,统计1的个数即可。
问题在于怎么降低求Bi的复杂度。 考虑到实际的bitset最多m种可能,可以利用这一性质想到排序后滚动bitset。
#pragma warning(disable:4996) #include<iostream> #include<algorithm> #include<bitset> #include<tuple> #include<unordered_map> #include<fstream> #include<iomanip> #include<string> #include<cmath> #include<cstring> #include<vector> #include<map> #include<set> #include<list> #include<queue> #include<stack> #include<sstream> #include<cstdio> #include<ctime> #include<cstdlib> #define INF 0x3f3f3f3f #define inf 0x7FFFFFFF #define MOD 998244353 #define moD 1000000003 #define pii pair<int,int> #define eps 1e-8 #define equals(a,b) (fabs(a-b)<eps) #define bug puts("bug") #define re register #define fi first #define se second const int maxn = 1e5 + 5e4 + 10; const double Inf = 10000.0; const double PI = acos(-1.0); typedef long long ll; typedef unsigned long long ull; using namespace std; bitset<maxn> ans, base; vector<pii> v1, v2; int main() { int n, m; int tmp; scanf("%d%d", &n, &m); for (int i = 0; i < n; i++) scanf("%d", &tmp), v1.emplace_back(tmp, i ); for (int i = 0; i < m; i++) scanf("%d", &tmp), v2.emplace_back(tmp, i); sort(v1.begin(), v1.end()); sort(v2.begin(), v2.end()); ans.set(); for (int i = m - 1, j = n - 1; i >= 0; i--) { while (j >= 0 && v1[j].first >= v2[i].first) { base.set(v1[j].se); j--; } ans &= base >> v2[i].se; } printf("%d", ans.count()); }