NC15332 B.小圆前辈的素数(fft+计数)

目录

Description

有两个数组,数组 \(a\) 中的每个数都可以与 \(b\) 中的数相加,求这 \(mn\) 个数中有多少数为质数

State

\(1<=n,m<=10^5\)

\(1<=a[i], b[i]<=10^5\)

Input

1
2 3
1 2
3 4 6

Output

3

Solution

要计算这 \(mn\) 个数的值并没有很好的办法,可以通过多项式相乘指数相加的方法求出这 \(mn\) 个数,再依次判断即可

因为取模的原因,\(ntt\) 可能造成答案并不准确,所以采用 \(fft\)

$hint: $ 一个质数可能出现多次; 而且有多组测试样例


Code

const int N = 4e5 + 5;

    int n, m, _, k;
    struct Complex
    {
        double x, y;
        Complex(double x = 0, double y = 0): x(x), y(y){}
        Complex operator+(const Complex &o) const{return{x+o.x,y+o.y};}  
        Complex operator-(const Complex &o) const{return{x-o.x,y-o.y};}  
        Complex operator*(const Complex &o) const{return{x*o.x-y*o.y,x*o.y+y*o.x};} 
    }a[N], b[N];

bool isp[N];
int prm[N / 10 + 5], tot = 0;
int get_p()
{
    fill_n(isp, N, 1);
    isp[0] = isp[1] = 0;
    for (ll i = 2; i < N; i++){
        if(isp[i]){
            prm[++ tot] = i;
        }
        for(int j = 1; j <= tot && prm[j] * i < N; j ++){
            isp[prm[j] * i] = 0;
            if(i % prm[j] == 0) break;
        }
    }
    return tot;
}

int lim = 1, rev[N], bit = 0;
void init(int n)
{
    while(lim <= n) lim *= 2, bit ++;
    for(int i = 0; i < lim; i ++){
        rev[i] = rev[i >> 1] >> 1 | ((i & 1) << (bit - 1));
    }
}

void fft(Complex *a, int type)
{
    for(int i = 0; i < lim; i ++){
        if(i < rev[i]) swap(a[i], a[rev[i]]);
    }
    for(int mid = 1; mid < lim; mid *= 2){
        Complex wn = Complex(cos(pi / mid), type * sin(pi / mid));
        for(int i = 0, len = mid * 2; i < lim; i += len){
            Complex w = Complex(1, 0);
            for(int j = 0; j < mid; j ++){
                Complex x = a[i + j], y = a[i + j + mid] * w;
                a[i + j] = x + y;
                a[i + j + mid] = x - y;
                w = w * wn;
            }
        }
    }
    if(type == 1) return ;
    for(int i = 0; i < lim; i ++){
        a[i].x = a[i].x / lim + 0.5;
    }
}

void clear()
{
    for(int i = 0; i <= lim; i ++){
        a[i].x = b[i].x = 0;
        a[i].y = b[i].y = 0;
    }
}

signed main()
{
    //IOS;
    get_p();
    init(2e5);
    rush(){
        sdd(n, m);
        rep(i, 1, n){
            sd(k);
            a[k].x ++;
        }
        rep(i, 1, m){
            sd(k);
            b[k].x ++;
        }
        fft(a, 1); fft(b, 1);
        for(int i = 0; i < lim; i ++){
            a[i] = a[i] * b[i];
        }
        fft(a, -1);
        ll ans = 0;
        for(int i = 2; i < lim; i ++){
            if(isp[i]) ans += a[i].x;
        }
        pll(ans);
        clear();
    }
    //PAUSE;
    return 0;
}
posted @ 2021-09-24 10:50  Bcoi  阅读(50)  评论(0)    收藏  举报