T1 守序划分问题

记划分后的集合为\(A_i\),全集\(U=\{i|1<=i<=m\}\)

题目限制等价于,一种集合划分合法,当且仅当\(\forall S\subset U且S!=\varnothing,\min A_{i\in S}<\max A_{j \not\in S}\)

证明充分性就构造然后归纳一下

将所有集合按min升序,设已经处理完 \(A_{p_{i-1}}\)且合法

由于\(\min A_{j\in[i,m]}=\min A_i\),根据条件可知,存在\(j\in[1,i-1]\)满足\(\max A_j>\min A_i\)

必要性是显然的

然后可以dp了,f[i][j][k]设前 i 个数划分到 j 个集合,有 k 个集合还未闭合

转移就分四种情况,是否闭合集合和是否新开集合

\[f[i][j][k]=f[i-1][j-1][k]+f[i-1][j-1][k-1]+(k+1)*f[i-1][j][k+1]+k*f[i-1][j][k] \]

还要注意边界

T2 欧拉函数

然而并没有写正解

加法还是比较好写的,就扫一遍\(p_i<=\sqrt {\sum a_j}\),复杂度是\(O(q\frac{\sqrt {nw}}{\log \sqrt {nw}})\)

对于乘法,每个数把质因数存进bitset里,每个线段树节点存一个bitset,然后就单点修改区间查询

bitset还有俩nb的函数,叫\(\_Find\_first,\_Find\_next\),找第一个1和下一个1

T3 点整的上圆

Min_25筛还没学,,,

代码

T1

#include<bits/stdc++.h>
using namespace std;
#define il inline
#define int long long
const int N=5e2+11;
const int mod=998244353;
int n,m;
int f[2][N][N];
il void md(int &x){if(x>=mod)x-=mod;return;}
il int read()
{
	int s=0;
	char ch=getchar();
	while(ch>'9'||ch<'0')ch=getchar();
	while(ch>='0'&&ch<='9')s=(s<<1)+(s<<3)+(ch^48),ch=getchar();
	return s;
}
signed main()
{
	freopen("partition.in","r",stdin);
	freopen("partition.out","w",stdout);
	n=read(),m=read();
	f[0][0][0]=1;
	bool now,last;
	for(int i=1;i<=n;++i)
	{
		now=i&1,last=now^1;
		for(int j=1;j<=m;++j)
		{
			for(int k=0;k<=j;++k)
			{
				md(f[now][j][k]+=f[last][j-1][k]);
				if(k) md(f[now][j][k]+=f[last][j-1][k-1]);
				md(f[now][j][k]+=(k+1)*f[last][j][k+1]%mod);
				md(f[now][j][k]+=k*f[last][j][k]%mod);
			}
			if(i!=n) f[now][j][0]=0;
		}
		memset(f[last],0,sizeof(f[last]));
	}
	cout<<f[now][m][0]<<endl;
	return 0;
}

T2

#include<bits/stdc++.h>
using namespace std;
#define il inline
#define int long long
const int B=4205;
const int N=4e4+11;
const int M=5e4+11;
const int mod=1e9+7;
struct tree{int l,r;bitset<B> bit;}tre[4*M];
int n,q;
bool fp[N];
int p[N],num,inv[N];
int a[M],tre1[M],tre2[M];
vector<int> vct[N];
bitset<B> bit;
int fm(int x,int y){int ans=1;for(;y;y>>=1,x=x*x%mod)if(y&1)ans=ans*x%mod;return ans;}
void insert1(int x,int val){for(;x<=n;x+=(x&-x))tre1[x]+=val;return;}
int query1(int x){int sum=0;for(;x;x-=(x&-x))sum+=tre1[x];return sum;}
void insert2(int x,int val){for(;x<=n;x+=(x&-x))tre2[x]=tre2[x]*val%mod;return;}
int query2(int x){int sum=1;for(;x;x-=(x&-x))sum=sum*tre2[x]%mod;return sum;}
il int read()
{
	int s=0;
	char ch=getchar();
	while(ch>'9'||ch<'0')ch=getchar();
	while(ch>='0'&&ch<='9')s=(s<<1)+(s<<3)+(ch^48),ch=getchar();
	return s;
}
void pre()
{
	fp[0]=fp[1]=1;
	inv[0]=inv[1]=1;
	for(int i=0;i<M;++i)tre2[i]=1;
	for(int i=2;i<N;++i)
	{
		if(!fp[i])p[++num]=i,vct[i].push_back(num);
		for(int j=1;j<=num&&p[j]*i<N;++j)
		{
			fp[i*p[j]]=1;
			vct[i*p[j]]=vct[i];
			if(i%p[j]==0) break;
			else vct[i*p[j]].push_back(j);
		}
		inv[i]=fm(i,mod-2);
	}
	return;
}
void build(int i,int l,int r)
{
	tre[i].l=l,tre[i].r=r;
	if(l==r){for(int x : vct[a[l]])tre[i].bit[x]=1;return;}
	int mid=(l+r)>>1;
	build(i<<1,l,mid);
	build(i<<1|1,mid+1,r);
	tre[i].bit=tre[i<<1].bit|tre[i<<1|1].bit;
	return;
}
void insert(int i,int x,int val)
{
	if(tre[i].l==tre[i].r){tre[i].bit.reset();for(int x : vct[val]) tre[i].bit[x]=1;return;}
	int mid=(tre[i].l+tre[i].r)>>1;
	if(x<=mid) insert(i<<1,x,val);
	else insert(i<<1|1,x,val);
	tre[i].bit=tre[i<<1].bit|tre[i<<1|1].bit;
	return;
}
bitset<B> query(int i,int l,int r)
{
	if(tre[i].l>=l&&tre[i].r<=r) return tre[i].bit;
	bitset<B> ans;ans.reset();
	int mid=(tre[i].l+tre[i].r)>>1;
	if(l<=mid) ans=query(i<<1,l,r);
	if(r>mid) ans|=query(i<<1|1,l,r);
	return ans;
}
int get_ans1(int l,int r)
{
	int sum=query1(r)-query1(l-1);
	int ans=sum%mod;
	int sq=sqrt(sum);
	for(int i=1;i<=num;++i)
	{
		if(p[i]>sq) break;
		if(sum%p[i]==0)
		{
			ans=ans*inv[p[i]]%mod*(p[i]-1)%mod;
			while(sum%p[i]==0)sum/=p[i];
		}
	}
	if(sum>1) ans=ans*fm(sum,mod-2)%mod*(sum-1)%mod;
	return ans;
}
int get_ans2(int l,int r)
{
	int ans=query2(r)*fm(query2(l-1),mod-2)%mod;
	bit.reset(),bit=query(1,l,r);
	for(int i=bit._Find_first();i<B;i=bit._Find_next(i)) if(bit[i]) ans=ans*inv[p[i]]%mod*(p[i]-1)%mod;
	return ans;
}
signed main()
{
	freopen("phi.in","r",stdin);
	freopen("phi.out","w",stdout);
	pre();
	n=read(),q=read();
	for(int i=1;i<=n;++i) a[i]=read(),insert1(i,a[i]),insert2(i,a[i]);
	build(1,1,n);
	for(int ty,l,r,x,i=1;i<=q;++i)
	{
		ty=read();
		if(!ty)
		{
			l=read(),x=read();
			insert(1,l,x);
			insert1(l,-a[l]),insert1(l,x);
			insert2(l,inv[a[l]]),insert2(l,x);
			a[l]=x;continue;
		}
		l=read(),r=read();
		if(ty==1)printf("%lld\n",get_ans1(l,r));
		else printf("%lld\n",get_ans2(l,r));
	}
	return 0;
}

相关文章:

  • 2021-11-28
  • 2021-12-04
  • 2022-03-03
  • 2021-07-18
  • 2021-10-26
  • 2021-12-13
  • 2021-11-21
猜你喜欢
  • 2021-11-04
  • 2022-02-18
  • 2021-09-02
  • 2021-07-23
  • 2021-09-06
  • 2022-12-23
  • 2022-01-21
相关资源
相似解决方案