• 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());
    }
  • 相关阅读:
    CSP-S2-2019游记
    【BZOJ2301】【HAOI2011】Problem B
    【NOIp2017】宝藏
    【NOIp2016】天天爱跑步
    【NOIp2018】保卫王国
    【BZOJ2159】Crash的文明世界
    Van爆零赛总结
    【ZJOI2016】小星星
    【CF1025D】Recovering BST
    【HAOI2016】字符合并
  • 原文地址:https://www.cnblogs.com/hznumqf/p/13296295.html
Copyright © 2020-2023  润新知