Loading

2020牛客多校补题 第二场

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());
}

 

posted @ 2020-07-13 22:26  MQFLLY  阅读(180)  评论(0编辑  收藏  举报