zoukankan      html  css  js  c++  java
  • steins;Gate

    题意

    (n)个数(a_1,a_2,dots,a_n)。对于每一个(a_k),求有多少个有序二元组((i,j))满足((a_i * a_j) mod(P) = a_k),其中(P)为一给定质数。

    (1 le N le 200000,2 le Ple 200000,0 le a_ile2100000000)

    符号

    g :(P)的原根

    题解

    因为(a_i mod P = g^t,(0 < t < P )),实际上转换成([ 0, P - 1))要方便很多。所以((a_i * a_j) mod(P) = ((a_i mod P) * (a_j mod P) mod(P)) = g^{t_1+t_2} mod (P) = a_k)。将乘法变成了加法,(FFT)就能用上了,和(hdu4609)的处理方法是一样的,kuangbin聚聚写的很清楚,也算是一个套路了。为什么要把模(P)等于0的数扣出来,因为这样的数是不能用原根表示的。

    代码

    const int N = 600010;
    
    struct Complex {
        double r,i;
        Complex(double real=0.0,double image=0.0) {
            r=real;
            i=image;
        }
        Complex operator +(const Complex o){return Complex(r+o.r,i+o.i);}
        Complex operator -(const Complex o){return Complex(r-o.r,i-o.i);}
        Complex operator *(const Complex o){return Complex(r*o.r-i*o.i,r*o.i+i*o.r);}
    } b[N];
    
    int rev(int id, int len) {
        int pos = 0;
        for (int i = 0; (1 << i) < len; ++i) {
            pos <<= 1;
            if (id & (1 << i)) pos |= 1;
        }
        return pos;
    }
    
    Complex A[N];
    
    void FFT(Complex *a, int len, int DFT) {
        rep(i, 0, len) A[rev(i, len)] = a[i];
        for (int s = 1; (1 << s) <= len; ++s) {
            int m = (1 << s);
            Complex wm = Complex(cos(DFT * 2 * PI / m), sin(DFT * 2 * PI / m));
            for (int i = 0; i < len; i += m) {
                Complex w = Complex(1, 0);
                for (int j = 0; j < (m >> 1); ++j) {
                    Complex t = A[i + j];
                    Complex u = w * A[i + j + (m >> 1)];
                    A[i + j] = t + u;
                    A[i + j + (m >> 1)] = t - u;
                    w = w * wm;
                }
            }
        }
        if (DFT == -1) rep(i, 0, len) A[i].r /= len, A[i].i /= len;
        rep(i, 0, len) a[i] = A[i];
    }
    
    int n, g, P;
    int a[N], id[N];
    
    LL ans[N];
    
    bool check(int g) {
        LL t = 1;
        rep(i, 1, P - 1) {
            t = t * g % P;
            if (t == 1) return 0;
        }
        return 1;
    }
    
    int qpow(int x, int y) {
        int res = 1;
        for (; y; x = 1ll * x * x % P, y >>= 1) if (y & 1) res = 1ll * res * x % P;
        return res;
    }
    
    int main()
    {
        sc(n), sc(P);
        for (int i = 2; ; ++i) if (check(i)) {
            g = i;
            break;
        }
    
        LL t = 1;
        rep(i, 1, P) {
            t = t * g % P;
            id[t] = i;
        }
    
        t = 0;
        Rep(i, 1, n) {
            sc(a[i]);
            if (a[i] % P == 0) t++;
            else b[id[a[i] % P]].r++;
        }
    
        int len = (1 << 19);
    
        FFT(b, len, 1);
        rep(i, 0, len) b[i] = b[i] * b[i];
        FFT(b, len, -1);
    
        // 当P = 2时,i = 0也有贡献
        rep(i, 0, len) ans[qpow(g, i)] += (LL)(b[i].r + 0.5);
    
        Rep(i, 1, n) {
            if (a[i] >= P) printf("0
    ");
            else if (a[i] == 0) printf("%lld
    ", t * t + 2 * t * (n - t));
            else printf("%lld
    ", ans[a[i]]);
        }
    
        return 0;
    }
    
    
  • 相关阅读:
    E4A易安卓3.6无需注册编译Release
    PHP中几种常用的网页跳转代码
    超详细教你重新封装GHO(ndeer和绿茶)教程
    程序员和编码员之间的区别
    迅闪三层下载游戏无速度
    POST注册DZ论坛或发帖
    解决局域网文件共享设置
    妻子 情人 红颜知己
    照片与同行元素居中的方法
    【转】SVN使用教程总结
  • 原文地址:https://www.cnblogs.com/zgglj-com/p/9749041.html
Copyright © 2011-2022 走看看