zoukankan      html  css  js  c++  java
  • UESTC 2014 Summer Training #16 Div.2

      虽然被刷了还是要继续战斗下去嗯...就是基础不好,难度相对较大

    A.SPOJ AMR10A

      点是顺时针给出的,可以在图上画画(脑补也行),连线x-a,x-b(x为选定的一个点,比如第一个点),就把所求面积分成了四部分,a-b左边部分是较容易求出来的,

    三角形面积是直接可求,另外两个多边形面积是可以预处理出来的(多个三角形面积和)

      反正我是沒想出來...看題解也理解半天,多邊形面積转化为三角形面积和 嗯嗯

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cmath>
    
    using namespace std;
    
    const int maxn = 50000+50;
    
    struct Point{
        long long x, y;
    
        Point() {}
    
        Point(long long x, long long y) {
            this->x = x;    this->y = y;
        }
    
    }a[maxn];
    
    int N, Q;
    long long sum[maxn];
    
    long long getArea(Point a, Point b, Point c)
    {
        return abs( (c.y-a.y)*(b.x-a.x)-(b.y-a.y)*(c.x-a.x) );
    }
    
    int main()
    {
    #ifdef LOCAL
        freopen("A.in", "r", stdin);
    #endif
        scanf("%d%d", &N, &Q);
        for(int i = 1; i <= N; i++) {
            long long x, y;
            scanf("%lld%lld", &x, &y);
            a[i] = Point(x, y);
        }
        for(int i = 3; i <= N; i++)
            sum[i] = sum[i-1] + getArea(a[1], a[i-1], a[i]);
        while(Q--) {
            int u, v;
            scanf("%d%d", &u, &v);
            u++;    v++;
            if(v < u)    swap(u, v);
            long long ans = sum[N] - sum[v] + getArea(a[1], a[u], a[v]) + sum[u];
            ans = min(ans, sum[N]-ans);
            if(ans%2 != 0)    printf("%lld.5
    ", ans/2);
            else    printf("%lld.0
    ", ans/2);
        }
        return 0;
    }

    C.SPOJ AMR11C

      可以转化为二分图的最大带权匹配问题,连边+KM

      连边朴素的dfs是会挂掉的,2^25,这里介绍一个方法解决这类求子集和的问题,meet-in-the-middle algorithm

      http://www-ti.informatik.uni-tuebingen.de/~reinhard/krypto/English/4.5.1.e.html

      大致意思是先预处理出前一半元素能组合出的数,2^13个,并且排序,然后枚举后一半能组合出的数s2,二分查找sum-s2是否存在,时间复杂度是可以接受的,具体看以上链接

      不过KM算法我不会呢...先扔这里吧

    F.SPOJ AMR10F

      水题

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    
    using namespace std;
    
    int T, N, A, D;
    
    int main()
    {
        cin >> T;
        while(T--) {
            cin >> N >> A >> D;
            cout << (2*A+(N-1)*D)*N/2 << endl;
        }
        return 0;
    }

    G.SPOJ AMR10G

      队友搞出来的...我没怎么思考,就是排序后,检查每一个区间的极差,算有点贪心,每次选取连续的k个

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <algorithm>
    
    using namespace std;
    
    const int maxn = 20000+50;
    const int inf = ~0u >> 1;
    
    int T, k, n;
    int h[maxn];
    
    int main()
    {
    #ifdef LOCAL
        freopen("G.in", "r", stdin);
    #endif
        scanf("%d", &T);
        while(T--) {
            scanf("%d%d", &n, &k);
            for(int i = 0; i < n; i++)
                scanf("%d", h+i);
            sort(h, h+n);
            int ans = inf;
            for(int i = 0; i+k <= n; i++)
                ans = min(h[i+k-1]-h[i], ans);
            printf("%d
    ", ans);
        }
        return 0;
    }

    H.SPOJ AMR10H

      贪心的做法,考虑最小的两个概率一定要放在最两边(选择最两边时,耗时最大)...不要问我为什么= =

      最后算下gcd除去就可以了  ps:  gcd(a,0) = a

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <algorithm>
    
    using namespace std;
    
    const int maxn = 40;
    
    int T, n, a, b, c;
    int p[maxn], arranged[maxn];
    
    int gcd(int a, int b)
    {
        return b == 0 ? a: gcd(b, a%b);
    }
    
    int main()
    {
    #ifdef LOCAL
        freopen("H.in", "r", stdin);
    #endif
        scanf("%d", &T);
        while(T--) {
            scanf("%d%d%d%d", &n, &a, &b, &c);
            for(int i = 0; i < n; i++)
                scanf("%d", p+i);
            sort(p, p+n);
            int front = 0, rear = n-1;
            for(int i = 0; i < n; i++)
                arranged[i%2?rear--:front++] = p[i];
            int ans = 0;
            for(int i = 0; i < n; i++)
                for(int j = 0; j < n; j++)
                    ans += arranged[i]*arranged[j]*((i-j)*(i-j)*a+b*abs(i-j)+c);
            printf("%d/%d
    ", ans/gcd(ans, 10000), 10000/gcd(10000, ans));
        }
        return 0;
    }

    I.SPOJ AMR10I

      这道题我是无论如何也想不到这样优化的...

      N=a1+a2+...+an,  P=a1a2...an

      a1...an都能唯一分解为素数相乘,因此P一定是2~N的素数乘积,似乎通过一个素数表来dfs

      现在要考虑另一点(很多blog没有指出) 最原始的办法是dfs 1~N 现在我们dfs这个素数表,是否覆盖了所有的情况呢?

      事实上2,3的组合就能覆盖2~N的所有数,即使用素数替换之前dfs的数

      例如10 = 6+4  原始的做法会去 dfs 4 6  而现在dfs  2 2 2 3 素数的组合

      想了半天其实自己也不是很理解...

      PS:第一次使用set 资料给出基本操作都是O(logn)!!

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <set>
    
    using namespace std;
    
    const int prime[] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71};  
    
    int T, N, P;
    set<long long> cnt;
    
    void dfs(int x, int r, long long p)
    {
        if(x >= 20)    return;
        cnt.insert(p);
    //    cout << "insert " << p <<endl;
        if(r < prime[x])    return;
        dfs(x, r-prime[x], p*prime[x]%P);
        //if(r < prime[x+1])    return;
        dfs(x+1, r, p);
    }
    
    int main()
    {
    #ifdef LOCAL
        freopen("I.in", "r", stdin);
    #endif
        scanf("%d", &T);
        while(T--) {
            scanf("%d%d", &N, &P);
            cnt.clear();
            dfs(0, N, 1ll);    
            printf("%d
    ", cnt.size());
        }
        return 0;
    }
  • 相关阅读:
    OSCP Learning Notes Buffer Overflows(3)
    OSCP Learning Notes Buffer Overflows(5)
    OSCP Learning Notes Exploit(3)
    OSCP Learning Notes Exploit(4)
    OSCP Learning Notes Exploit(1)
    OSCP Learning Notes Netcat
    OSCP Learning Notes Buffer Overflows(4)
    OSCP Learning Notes Buffer Overflows(1)
    OSCP Learning Notes Exploit(2)
    C++格式化输出 Learner
  • 原文地址:https://www.cnblogs.com/gemmeg/p/3898726.html
Copyright © 2011-2022 走看看