原文链接https://www.cnblogs.com/zhouzhendong/p/CF1016G.html

题目传送门 - CF1016G

题意

  给定 $n,x,y$ ,以及一个含有 $n$ 个元素的数组 $a$ 。

  我们称一个数对 $(i,j)$ 是合法的,当且仅当存在一个 $v$ ,使得 $\gcd(a_i,v)=x$ 且 ${\rm lcm} (a_j,v)=y$ 。

  请你统计有多少合法的 $(i,j)$ 数对。

  $n\leq 2\times 10^5,1\leq x,y,a_i\leq 10^{18}$

题解

  先用 Pollard_Rho 将 $y$ 分解一下。由于最小的 $16$ 个不同的质数的乘积大于 $10^{18}$ ,所以, $y$ 最多只有 $15$ 个不同的质因子。

  然后,我们罗列以下简单性质:

  性质1 : $x|y$ 。 证明: 因为 $\gcd(a_i,v)=x$ ,所以 $x|v$ ; 因为 ${\rm lcm}(a_j,v)=y$ ,所以 $v|y$ 。因为 $x|v,v|y$ ,所以 $x|y$ 。

  性质2 : $x|a_i,\ \ \ \ a_j|y$ 。

  性质3 : 令集合 $P$ 为素数集。定义一个数 $\alpha$ 分解质因数后,得到的结果中,含有质因子 $p(p\in P)$ 的个数为 $c_{a_i,p}$ 。则因为 $x|y$ ,所以 $\forall p\in P , c_{x,p}\leq c_{y,p}$ 。

  性质4 : 数对 $(i,j)$ 是合法的,对应的数是 $v$ 。那么 $\forall p\in P, c_{x,p}\leq \min(c_{a_i,p},c_{v,p}),\max(c_{a_j,p},c_{v,p})\leq c_{y,p}$ 。

  于是,我们就可以得到快速判定两个 $(i,j)$ 是否合法了。

  性质5 : $X=\{a_i\} (x|a_i),Y=\{a_i\} (a_i|y)$ ,如果一个数对 $(i,j)$ 合法,则根据性质2和性质4,必然有: $a_i\in X,a_j\in Y;\ \ \forall p\in P, c_{a_i,p}=c_{x,p} 或 c_{a_j,p}=c_{y,p}$ 。

  由于一开始说到的, $y$ 最多只有 $15$ 个不同的质因子,所以对于 $p\in P$ 且 $c_{y,p}=0$ ,由于 $a_j|y$ ,所以 $c_{a_j,p}=c_{y,p}=0$ ,所以这个不需要考虑。

  考虑枚举 $a_i\in X$ ,对于一个数 $i$ ,对应的合法的 $j$ 有多少?我们考虑写出合法的 $a_j$ 的范围。

  对于每一个 $p\in P$ ,那么我们需要询问的是一下两种情况下满足条件的数的个数:如果 $c_{a_i,p}=c_{x,p}$ , $c_{a_j,p}=c_{y,p}\ {\rm OR}\ c_{a_j,p}<c_{y,p}$ ;如果 $c_{a_i,p}>c_{x,p}$ ,那么 $c_{a_j,p}=c_{y,p}$ 。

  由于我们最多只需要涉及 $15$ 个质因子,我们可以把集合 $y$ 中的数的信息压缩一下,得到一个二进制表示。令 $y$ 的第 $i$ 个质数为 $p_i$ ,则对于一个数 $a_j$ ,如果 $c_{a_j,p_i}=c_{y,p_i}$ 那么对应二进制位为 $1$ ,否则为 $0$ 。于是,每一次询问就是要求一下对应的数的个数。不难发现,我们只需要统计一下每一个二进制表示对应的在集合 $y$ 中有多少数字,然后做一个 and 卷积的FWT,就可以得到需要询问的东西了。

  令 $d=15$ ,所以时间复杂度为 $O ((n+2^d)\log d)$ 。

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef long double LD;
namespace Pollard_Rho{
int prime[9]={2,3,5,7,11,13,17,19,23};
ULL RR;
int Pcnt;
LL p[70];
vector <LL> res;
LL R(LL mod){
return (RR+=4179340454199820289LL)%mod;
}
LL Mul(LL x,LL y,LL mod){
LL d=(LL)floor((LD)x*y/mod+0.5);
LL res=x*y-d*mod;
if (res<0)
res+=mod;
return res;
}
LL Pow(LL x,LL y,LL mod){
LL ans=1%mod;
for (;y;y>>=1,x=Mul(x,x,mod))
if (y&1)
ans=Mul(ans,x,mod);
return ans;
}
bool Miller_Rabin(LL n){
if (n<=1)
return 0;
for (int i=0;i<9;i++)
if (n==prime[i])
return 1;
LL d=n-1;
int tmp=0;
while (!(d&1))
d>>=1,tmp++;
for (int i=0;i<9;i++){
LL x=Pow(prime[i],d,n),p=x;
for (int j=1;j<=tmp;j++){
x=Mul(x,x,n);
if (x==1&&p!=1&&p!=n-1)
return 0;
p=x;
}
if (x!=1)
return 0;
}
return 1;
}
LL f(LL x,LL c,LL mod){
return (Mul(x,x,mod)+c)%mod;
}
LL gcd(LL x,LL y){
return y?gcd(y,x%y):x;
}
LL Get_Factor(LL c,LL n){
LL x=R(n),y=f(x,c,n),p=n;
while (x!=y&&(p==n||p==1)){
p=gcd(n,max(x-y,y-x));
x=f(x,c,n);
y=f(f(y,c,n),c,n);
}
return p;
}
void Pollard_Rho(LL n){
if (n<=1)
return;
if (Miller_Rabin(n)){
res.push_back(n);
return;
}
while (1){
LL v=Get_Factor(R(n-1)+1,n);
if (v!=n&&v!=1){
Pollard_Rho(v);
Pollard_Rho(n/v);
return;
}
}
}
void work(LL n){
res.clear();
Pollard_Rho(n);
}
}
LL read(){
LL x=0,f=1;
char ch=getchar();
while (!isdigit(ch)&&ch!='-')
ch=getchar();
if (ch=='-')
f=-1,ch=getchar();
while (isdigit(ch))
x=(x<<1)+(x<<3)+ch-48,ch=getchar();
return x;
}
const int N=200005;
int n;
LL x,y,a[N];
LL v[16],vc=0,xc[16],yc[16],c[16];
vector <LL> Mul_x;
LL A[1<<15];
void Get_V(){
memset(xc,0,sizeof xc);
memset(yc,0,sizeof yc);
Pollard_Rho :: work(y);
vector <LL> xx=Pollard_Rho :: res;
sort(xx.begin(),xx.end());
v[vc=1]=xx[0],yc[vc]=1;
for (int i=1;i<xx.size();i++)
if (xx[i]==xx[i-1])
yc[vc]++;
else
v[++vc]=xx[i],yc[vc]=1;
LL xv=x;
for (int i=1;i<=vc;i++)
while (xv%v[i]==0)
xv/=v[i],xc[i]++;
}
void FWT(LL a[],int n,int flag){
for (int d=1;d<n;d<<=1)
for (int i=0;i<n;i+=(d<<1))
for (int j=0;j<d;j++)
a[i+j]+=a[i+j+d]*flag;
}
int main(){
n=read(),x=read(),y=read();
for (int i=1;i<=n;i++)
a[i]=read();
if (y%x){
putchar('0');
return 0;
}
if (y==1){
int ans=0;
for (int i=1;i<=n;i++)
if (a[i]==1)
ans++;
printf("%I64d",1LL*ans*ans);
return 0;
}
Get_V();
Mul_x.clear();
memset(A,0,sizeof A);
for (int i=1;i<=n;i++){
if (a[i]%x==0)
Mul_x.push_back(a[i]);
if (y%a[i]==0){
memset(c,0,sizeof c);
LL yv=a[i];
for (int i=1;i<=vc;i++)
while (yv%v[i]==0)
yv/=v[i],c[i]++;
int s=0;
for (int i=1;i<=vc;i++)
if (c[i]==yc[i])
s|=1<<(i-1);
A[s]++;
}
}
FWT(A,1<<vc,1);
LL ans=0;
for (int i=0;i<Mul_x.size();i++){
LL now=Mul_x[i];
memset(c,0,sizeof c);
LL yv=now;
for (int i=1;i<=vc;i++)
while (yv%v[i]==0)
yv/=v[i],c[i]++;
int s=(1<<vc)-1;
for (int i=1;i<=vc;i++)
if (c[i]==xc[i]||xc[i]==yc[i])
s^=1<<(i-1);
ans+=A[s];
}
printf("%I64d",ans);
return 0;
}

  

Codeforces 1016G Appropriate Team 数论 FWT的更多相关文章

  1. [CodeForces - 1225C]p-binary 【数论】【二进制】

    [CodeForces - 1225C]p-binary [数论][二进制] 标签: 题解 codeforces题解 数论 题目描述 Time limit 2000 ms Memory limit 5 ...

  2. Codeforces 1045B Space Isaac - 数论 - Hash

    题目传送门 传送门I 传送门II 传送门III 题目大意 给定将$\left \{ 0, 1, \dots, m - 1\right \}$分成了不相交的两个非空集合$A$和$B$,给定$A$,问存在 ...

  3. CodeForces - 615D Multipliers(数论)

    http://codeforces.com/problemset/problem/615/D 题意 给出m个质因子,组成一个数n.问n的约数的乘积是多少,输出mod 1e+7的结果. 分析 从输入我们 ...

  4. Codeforces Round #425 (Div. 2) Problem C Strange Radiation (Codeforces 832C) - 二分答案 - 数论

    n people are standing on a coordinate axis in points with positive integer coordinates strictly less ...

  5. Codeforces 932 E. Team Work(组合数学)

    http://codeforces.com/contest/932/problem/E 题意:   可以看做 有n种小球,每种小球有无限个,先从中选出x种,再在这x种小球中任选k个小球的方案数 选出的 ...

  6. Codeforces 932.E Team Work

    E. Team Work time limit per test 2 seconds memory limit per test 256 megabytes input standard input ...

  7. Codeforces 757 F Team Rocket Rises Again

    Discription It's the turn of the year, so Bash wants to send presents to his friends. There are n ci ...

  8. codeforces 615 D. Multipliers (数论 + 小费马定理 + 素数)

    题目链接: codeforces 615 D. Multipliers 题目描述: 给出n个素数,这n个素数的乘积等于s,问p的所有因子相乘等于多少? 解题思路: 需要求出每一个素数的贡献值,设定在这 ...

  9. codeforces 108D Basketball Team(简单组合)

    D. Basketball Team time limit per test 2 seconds memory limit per test 256 megabytes input standard ...

随机推荐

  1. Android获取本机号码及运营商

    import android.content.Context; import android.telephony.TelephonyManager; import android.util.Log; ...

  2. swift 学习- 26 -- 泛型

    // 泛型 代码能够让你根据自定义的需求,编写出适用于任意类型, 灵活可重用的函数以及类型, 它能让你避免代码的重复, 用一种清晰和抽象的方式来表达代码的意图 // 泛型是 Swift 最强大的特性之 ...

  3. gnuradio 创建动态库 libftd3xx.so

    首先还是创建好模块gr-kcd cd gr-kcd 打开CMakeLists.txt cmake_minimum_required(VERSION 2.6) project(gr-kcd CXX C) ...

  4. kafka消息的分发与消费

    关于 Topic 和 Partition: Topic: 在 kafka 中,topic 是一个存储消息的逻辑概念,可以认为是一个消息集合.每条消息发送到 kafka 集群的消息都有一个类别.物理上来 ...

  5. cf1132G 线段树解分区间LIS(一种全新的线段树解LIS思路)+单调栈

    /* 给定n个数的数列,要求枚举长为k的区间,求出每个区间的最长上升子序列长度 首先考虑给定n个数的数列的LIS求法:从左往右枚举第i点作为最大点的贡献, 那么往左找到第一个比a[i]大的数,设这个数 ...

  6. 拓展中国剩余定理(ex_crt)

    一般来讲,crt(中国剩余定理)比较常见,而ex_crt(拓展中国剩余定理)不是很常用 但是noi 2018偏偏考了这么个诡异的东西... 所以这里写一个ex_crt模板 模型: 求一个x满足上述方程 ...

  7. swagger2常用注解说明

    说明: 1.这里使用的版本:springfox-swagger2(2.4)springfox-swagger-ui (2.4) 2.这里是说明常用注解的含义和基本用法(也就是说已经对swagger进行 ...

  8. python2.7 (x64) 调用 java 代码实践

    背景:公司实施接口自动化测试,使用的框架python+unittest:因为开发使用的架构师SpringBoot,在测试过程中难免需要使用到python调用JAVA的一些接口,所以需要用到python ...

  9. java中的相对目录问题

    在java开发过程中,常常需要使用本地文件内容文件.在调试他人代码的过程中,可能不经意间改变了源代码的根目录(顶级目录),从而导致“java io filenotfoundexception ”.解决 ...

  10. 饮冰三年-人工智能-linux-06 系统启动流程及安全

    系统启动流程 BOIS(Basic Input/Output System)基本输入输出系统:硬件和软件之间的接口,而且是很基本的接口. grub(Grand Unified BootLoader)多 ...