zoukankan      html  css  js  c++  java
  • HDU多校2017第7场

    6121 Build a tree

    6125 Free from square

    6126 Give out candies

    6127 Hard challenge

    6128 Inverse of sum

    式子$frac{1}{a+b}equiv frac{1}{a}+frac{1}{b}(mod p)$可化为$a^2+ab+b^2 equiv 0(mod p)$。当$a=b$时,可转化为$3a^2 equiv 0(mod p)$,此时,只有$p=3$时才成立(因为$p$必须是素数)。当$a e b$时,把式子$a^2+ab+b^2 equiv 0(mod p)$两边同时乘$(a-b)$,得到$a^3-b^3 equiv 0(mod p),Longrightarrow a^3 equiv b^3(mod p)$。

    因此:

    当$p=3$时,只需要分别统计$1$和$2$的个数$cnt1$和$cnt2$,答案就是$A_{cnt1}^2+A_{cnt2}^2$。

    当$p e 3$时,必然是$a e b$,对于元素$x$而言,需要找到一些$y$,满足:$x e y$且$x^3 equiv y^3(mod p)$。这时,因为$max(p)=10^{18}$,计算$y^3(mod p)$时会溢出,所以需要用到快速乘法

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    #define MAXN 100010
    LL a[MAXN], n, p;
    
    LL calc(){
        LL res = 0;
        a[n] = -1;
        for(int i = 1, cnt = 1;i <= n;++i){
            if(a[i] == a[i - 1])cnt++;
            else{
                res += LL(cnt - 1) * cnt / 2;
                cnt = 1;
            }
        }
        return res;
    }
    
    LL qmult(LL x, LL y){
        LL res = 0;
        if(x < y)swap(x, y);
        while(y){
            if(y & 1)res = (res + x) % p;
            x = (x << 1) % p;
            y >>= 1;
        }
        return res;
    }
    
    int main(){
        int T;
        scanf("%d", &T);
        while(T--){
            scanf("%I64d%I64d", &n, &p);
            for(int i = 0;i < n;++i)scanf("%I64d", a + i);
            if(p == 3){
                int cnt1 = 0, cnt2 = 0;
                for(int i = 0;i < n;++i){
                    if(a[i] == 1)cnt1++;
                    else if(a[i] == 2) cnt2++;
                }
                LL ans = LL(cnt1 - 1) * cnt1 / 2 + LL(cnt2 - 1) * cnt2 / 2;
                cout << ans << endl;
            }else{
                sort(a, a + n);
                LL ans = -calc();
                for(int i = 0;i < n;++i)a[i] = qmult(a[i], qmult(a[i], a[i]));
                sort(a, a + n);
                ans += calc();
                cout << ans << endl;
            }
        }
        return 0;
    }

    6129 Just do it

    对于变换$m$次之后的序列,考虑$a_0$对$a_i(0 le i < n)$的贡献,为$C_{m-1+i}^i$个$a_0$相异或的结果。同样地,$a_1$对$a_{i+1}(0 le i<n-1)$的贡献也为$C_{m-1+i}^i$。然后,组合数判定奇偶性:杨辉三角第$i$行第$j$列的元素为$C_i^j$,如果$(i & j) == j$,则$C_i^j$为奇数,否则为偶数。接下来,只需要枚举$a_0$对$a_i(0 le i < n)$的贡献,若为奇数,则$a_1$对$a_{i+1}$的贡献,$a_2$对$a_{i+2}$的贡献,$dots$,只需要暴力做相同的处理即可。放心,不会超时的。我随机造了几十组数据规模$2 imes 10^5$的大数据,有的数据需要迭代近$4 imes 10^8$次,只需要300+ms左右就能迭代完。下面的代码通过hdu所有数据的测试,只需要900+ms。而且是在没做任何常数优化的情况下。

    另外,杨辉三角具有一个性质:用$P_n$表示$n$层三角形中奇数的占比,有:${limlimits_{n o infty}P_n o 0}$。

    #include<bits/stdc++.h>
    using namespace std;
    #define MAXN 200010
    int a[MAXN], b[MAXN], n, m;
    int main(){
        //freopen("input.txt", "r", stdin);
        int T;
        scanf("%d", &T);
        while(T--){
            scanf("%d%d", &n, &m);
            for(int i = 0;i < n;++i)scanf("%d", a + i);
            memset(b, 0, sizeof(b));
            for(int i = 0;i < n;++i){
                if((((m - 1) + i) & i) == i){
                    for(int j = i, k = 0;j < n;++j,++k){
                        b[j] ^= a[k];
                    }
                }
            }
    //        cout << cnt << " " << clock() - st << endl;
            for(int i = 0;i < n;++i)printf("%d%c", b[i], i == n - 1 ? '
    ' : ' ');
        }
        return 0;
    }
  • 相关阅读:
    就打排序算法总结
    php 垃圾回收机制写时复制和引用计数
    zend studio 使用断点调试
    SiteServer 迁移至 Windows 2008 R2 问题汇总
    [项目改造中的点滴]C#中IDataReader和DataSet的区别与使用场景
    顺序分支知识总结
    我的第一篇博客
    [原创]删除GRUB引导恢复Windows引导,不用下载任何工具
    在C++builder中使用正则表达式,非boost库,简单!~
    SQL 存储过程优化经验
  • 原文地址:https://www.cnblogs.com/dowhile0/p/9344697.html
Copyright © 2011-2022 走看看