原文链接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. gdb 调试程序步骤

    在程序a.c编译过程中加入调试信息: g++ -g -o a.debug a.c 启动gdb,在终端下输入:gdb 此时启动了gdb,在gdb中加载需要调试的程序,在终端输入命令: file a.de ...

  2. appium+java(二)appium初始化参数部分详解

    Capabilities介绍 实际上它的全称是:Desired capabilities Desired capability是一个JSON对象,包含一组key和value值.它由客户端发送给服务端, ...

  3. PHP use闭包函数

    <?php class Cart { //产品价格 const PRICE_BUTTER = 1.00; const PRICE_MILK = 3.00; const PRICE_EGGS = ...

  4. html跳转指定位置-利用锚点

    比如我现在 a.html 的时候,我想跳转到 b.html ,并且是 b.html 的某一个位置,用 <a href=>, a.html里: <a href="b.html ...

  5. 反转链表算法Java实现

    之前遇到反转链表的算法,比较晦涩难解,但其实挺简单的. 目标:将一个顺序链表反转. 思路:用三个辅助节点,每次实现一个节点的指向反转,即他的后继变为他的前驱. 三个辅助节点: p  q  r  按顺序 ...

  6. CentOS 7 连接ssh方法

    自己在VMware中装了CentOS 6.3,然后主机(或者说xshell)与里面的虚拟机连不通,刚学习,一头雾水,查了半天,也不知道怎么弄. 经指点,找到下面这篇文章,感谢博主: http://bl ...

  7. ORA-00257: archiver error. Connect internal only, until freed.| Oracle数据库归档日志满导致应用系统反应缓慢的问题处理

    一:查看原因 查看了下V$FLASH_RECOVERY_AREA_USAGE,看看归档目录使用的情况.果然是归档满了. Disconnected from Oracle Database 11g En ...

  8. OCP 相关课程列表

    OCP 相关课程列表 第一天:Linux基础 和 Oracle 11 R2 数据库安装教程图解 1:< VM 安装 linux Enterprise_R5_U4_Server_I386_DVD教 ...

  9. 【CSS】Bootstrap中select2+popover冲突

    网上搜索得到: It changes the position because the position is based on the popover's dimansions and select ...

  10. 第十六单元 yum管理RPM包

    yum的功能 本地yum配置 光盘挂载和镜像挂载 本地yum配置 网络yum配置 网络yum配置 Yum命令的使用 使用yum安装软件 使用yum删除软件 安装组件 删除组件 清除缓存 查询 课后作业 ...