Vasilije Loves Number Theory 题解
Vasilije Loves Number Theory 题解
思路
问题在于如何化简 \(d(na)= n\),就这么看的话十分难受。
可以推出一个式子:
\[d(xy)= d(x)\times d(y)
\]
因为太简单所以不给证明了,手玩几组数据也可以看出来。
所以以上的式子可以化简为 \(d(na)= d(n)\times d(a)= n\)。
即 \(d(a)= \dfrac{n}{d(n)}\)。
我们只考虑 \(a\) 是否存在,并且只要 \(d(a)\) 存在那么 \(a\) 就存在,所以实际上只需判断 \(d(n)\) 是否能被 \(n\) 整除就可以了。
直接算的话复杂度是极高的,最坏情况可以超过\(O(\sqrt{10^{6000}})\)。
考虑优化。
可以想到对 \(d(n)\) 与 \(n\) 质因数分解,然后遍历 \(d(n)\) 的质因数,如果存在某一项的指数大于分解后 \(n\) 相应的质因数的指数,说明不符合条件,否则符合。
对于 \(n\gets n\times x\) 这个操作,我们不需要重新计算 \(n\) 的质因子,只需要将 \(x\) 的质因子加入 \(n\) 中就可以了。
这样我们每次都只需处理新加入的 \(x\),运行时间大大缩短。
最后因为质因数太大需要一个 map 维护。
Code
#include<bits/stdc++.h>
#define ll long long
#define inf 0x3f3f3f3f
#define il inline
#define db double
#define F(i,a,b) for(int i=(a);i<=(b);i++)
#define f(i,a,b) for(int i=(a);i>=(b);i--)
#define MIN(x,y) (x<y?x:y)
#define MAX(x,y) (x>y?x:y)
il int read(){int w=1,c=0;char ch=getchar();for(;ch>'9'||ch<'0';ch=getchar()) if(ch=='-') w=-1;for(;ch>='0'&&ch<='9';ch=getchar()) c=(c<<3)+(c<<1)+ch-48;return w*c;}
void printt(int x){if(x>9) printt(x/10);putchar(x%10+48);}
il void print(int x){if(x<0) putchar('-'),printt(-x);else printt(x);}
il void put(int x){print(x);putchar('\n');}
int n,q;
int ddd,now;//ddd为初始d(n),now为现在d(n)
std::map<int,int> t,cs;//cs为n质因子的初始状态,t为现在n质因子的状态
bool pd()
{
int tmp=now;
for(int i=2;i*i<=tmp;i++)
{
if(tmp%i==0)
{
int cnt=0;
while(tmp%i==0) cnt++,tmp/=i;
if(cnt>t[i]) return 0;//如果d(n)有一个质因子的指数比n分解后的这个质因子的指数大,说明不符合要求
}
}
if(tmp!=1&&!t[tmp]) return 0;//同理,不符合条件
return 1;
}
il void init()//处理两个初始状态
{
ddd=1;//需要初始化为1方便后续乘法
for(int i=2;i*i<=n;i++)//处理n的质因子
{
if(n%i==0)
{
int cnt=0;//cnt为相应质因子的指数
while(n%i==0) cnt++,n/=i;
ddd*=cnt+1,cs[i]=cnt;//因子的个数就是质因子的指数+1的乘积
}
}
if(n>1) ddd*=2,cs[n]++;//还剩下一个质数
now=ddd,t=cs;
}
il void pri(int x)
{
for(int i=2;i*i<=x;i++)
{
if(x%i==0)
{
now/=t[i]+1;
while(x%i==0) t[i]++,x/=i;
now*=t[i]+1;
}
}
if(x>1)
{
now/=t[x]+1;
t[x]++;
now*=t[x]+1;
}
}
void solve()
{
t.clear(),cs.clear();
n=read(),q=read();
init();
int op,x;
while(q--)
{
op=read();
if(op==2) t=cs,now=ddd;//变为初始状态
else
{
x=read();
pri(x);//将x的质因数加入
puts(pd()?"YES":"NO");
}
}
puts("");//多输出一个空格
}
signed main()
{
int T;
T=read();
while(T--) solve();
}