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();
}
posted @ 2024-02-21 20:25  inlinexhx  阅读(6)  评论(0编辑  收藏  举报