列表

详情


NC222294. 数学家的迷题

描述

伟大的数学家费牛于自己的家中过世,桌上的纸笔记录着他生前研究的最后一个问题。

这个问题是这样的,首先给出个数字,第个数字为。接下来进行次操作,每次操作的类型如下:

1:将的值改为

2:令,求能被多少个不同的素数整除。

这种问题自然是难不倒费牛,可是他在草稿纸上写着:“我已经想到了一个绝妙的方法,可惜这儿空白太小写不下”。

没办法,现在只能请你代替费牛回答每个类型问题的答案。

输入描述

第一行两个正整数,,其中,

第二行个正整数

接下来行,每行第一个数字表示操作类型,

,输入正整数,其中,

,输入正整数,其中

输出描述

输出每个类型问题的答案。

示例1

输入:

5 3
2 3 6 6 6
2 1 4
1 4 5
2 1 4

输出:

2
3

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++ 解法, 执行用时: 424ms, 内存消耗: 154696K, 提交时间: 2021-06-25 22:01:39

#include<bits/stdc++.h>
using namespace std;

bitset<9600>s,S[200005];
int L=0,T[9600];
bool V[100005]={0};
void update(int L,int R,int pos,int rt)
{
	if(L==pos&&R==pos)
	{
		S[rt]=s;
		return;
	}
	int M=(L+R)>>1;
	if(M>=pos)update(L,M,pos,rt<<1);
	if(M<pos)update(M+1,R,pos,rt<<1|1);
	S[rt]=S[rt<<1]|S[rt<<1|1];
}
void search(int L,int R,int l,int r,int rt)
{
	if(l<=L&&R<=r)
	{
		s|=S[rt];
		return;
	}
	int M=(L+R)>>1;
	if(M>=l)search(L,M,l,r,rt<<1);
	if(M<r)search(M+1,R,l,r,rt<<1|1);
}
int main()
{
	int i,j,cnt,n,m,op,l,r,id,x;
    for(i=2;i<=1e5;i++)
    {
    	if(!V[i])T[L++]=i;
    	for(j=0;j<L&&T[j]*i<=1e5;j++)
    	{
    		V[i*T[j]]=1;
    		if(i%T[j]==0)break;
		}
	}
	scanf("%d%d",&n,&m);
	for(i=1;i<=n;i++)
	{
		scanf("%d",&x),s.reset();
		for(j=0;T[j]*T[j]<=x;j++)
		{
			for(cnt=0;x%T[j]==0;x/=T[j])cnt++;
			if(cnt)s[j]=1;
		}
		if(x!=1)j=lower_bound(T,T+L,x)-T,s[j]=1;
		update(1,n,i,1);
	}
	while(m--)
	{
		scanf("%d",&op);
		if(op==1)
		{
			scanf("%d%d",&id,&x),s.reset();
			for(j=0;T[j]*T[j]<=x;j++)
			{
				for(cnt=0;x%T[j]==0;x/=T[j])cnt++;
				if(cnt)s[j]=1;
			}
			if(x)j=lower_bound(T,T+L,x)-T,s[j]=1;
			update(1,n,id,1);
		}
		else
		{
			scanf("%d%d",&l,&r);
			s.reset(),search(1,n,l,r,1);
			printf("%d\n",s.count());
		}
	}
    return 0;
}

上一题