返回顶部

【比赛】高一下三调2

T1

[TJOI2013] 攻击装置

题目描述

给定一个 01 矩阵,其中你可以在 0 的位置放置攻击装置。每一个攻击装置 \((x,y)\) 都可以按照“日”字攻击其周围的 \(8\) 个位置 \((x-1,y-2)\)\((x-2,y-1)\)\((x+1,y-2)\)\((x+2,y-1)\)\((x-1,y+2)\)\((x-2,y+1)\)\((x+1,y+2)\)\((x+2,y+1)\)

求在装置互不攻击的情况下,最多可以放置多少个装置。

输入格式

第一行一个整数 \(N\),表示矩阵大小为 \(N \times N\)

接下来 \(N\) 行每一行一个长度 \(N\) 的 01 串,表示矩阵。

输出格式

一个整数,表示在装置互不攻击的情况下最多可以放置多少个装置。

样例 #1

样例输入 #1

3
010
000
100

样例输出 #1

4

提示

对于 \(30\%\) 的数据,保证 \(N \le 50\)

对于 \(100\%\) 的数据,保证 \(N \le 200\)

这道题,很显然是两个"对象"之间的关系,我们可以想到二分图求最大独立集,然后如何连边呢,连边我们俩可以通过给点新加编号1~\(n^2\),然后8个方向,每个点只需考虑\((x-1,y+2)\)\((x-2,y+1)\),\((x-1,y-2)\)\((x-2,y-1)\)这四个方向,这算一个优化(当然你也可以不考虑),然后关键是遍历用匈牙利求时时不成立的点要忽略(考试时遗漏了,听取Wa声一片),如果你奇偶判断的话,答案不用除以2,如果不奇偶的话,答案要除以2,左右集合种类一样二分图匈牙利算法求的是双向边

	for(int i=1;i<=tot;i++)
	{
			++now;
			if(dfs(i,now))ans++;//这是错的,无法判断是否为非法点			
	}
点击查看代码
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N =505;
int n,a[N][N],match[N*N],g[N][N],head[N*N],cnt,ju[N][N];int vis[N*N];
int x[10]={0,-1,-2,-1,-2,1,2,1,2};
int y[10]={0,-2,-1,2,1,-2,-1,-2,-1};
struct  Edge
{
	int u,to,next;
}edge[N*N*2];
void add(int u,int v)
{
	edge[++cnt].u=u;
	edge[cnt].to=v;
	edge[cnt].next=head[u];
	head[u]=cnt;
}
bool dfs(int now,int id)
{
	for(int i=head[now];i;i=edge[i].next)
//	for(int i=1;i<=n;i++)
	{
		int to=edge[i].to;
		if(to==now)continue;
//		int to=i;
		if(vis[to]!=id)
		{
			vis[to]=id;
			if(!match[to]||dfs(match[to],id))
			{
				match[to]=now;
				return true;
			}
		}
	}
	return false;
}
int tmp=0;
int xly()
{
	int ans=0,now=0;
	for(int i=1;i<=n;i++)
	for(int j=1;j<=n;j++)
	{
		if(!a[i][j])//&&(i+j)&1
		{
			++now;
			if(dfs(ju[i][j],now))ans++;			
		}

	}
	return ans;
}
int main()
{
//	freopen("attack.in","r",stdin);
//	freopen("attack.out","w",stdout);
	scanf("%d",&n);
	int x1,tot=0;;
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			scanf("%1d",&x1);
			a[i][j]=x1;tot+=(!x1);
			ju[i][j]=++tmp;
		}
	}
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			if(a[i][j])continue;
			for(int k=1;k<=8;k++)
			{
				int yy=j+y[k];
				int xx=i+x[k];
				if(xx>0&&yy>0&&yy<=n&&xx<=n&&!a[xx][yy])
				{
					add(ju[i][j],ju[xx][yy]);
					add(ju[xx][yy],ju[i][j]);
				}
			}
		}
	}
	cout<<tot-xly()/2<<endl;//tot-xly()
	return 0;
}
/*
3
010
000
100
*/
考试代码改正
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N =505;
int n,a[N][N],match[N*N],g[N][N],head[N*N],cnt,ju[N][N];int vis[N*N];
int x[10]={0,-1,-2,-1,-2,1,2,1,2};
int y[10]={0,-2,-1,2,1,-2,-1,-2,-1};
struct  Edge
{
	int u,to,next;
}edge[N*N*2];
void add(int u,int v)
{
	edge[++cnt].u=u;
	edge[cnt].to=v;
	edge[cnt].next=head[u];
	head[u]=cnt;
}
bool dfs(int now,int id)
{
	for(int i=head[now];i;i=edge[i].next)
//	for(int i=1;i<=n;i++)
	{
		int to=edge[i].to;
		if(to==now)continue;
//		int to=i;
		if(vis[to]!=id)
		{
			vis[to]=id;
			if(!match[to]||dfs(match[to],id))
			{
				match[to]=now;
				return true;
			}
		}
	}
	return false;
}
int tmp=0,tot;
bool ilegal[N*N];
int xly()
{
	int ans=0,now=0;
	for(int i=1;i<=tmp;i++)
	{
		if(!ilegal[i])//&&(i+j)&1
		{
			++now;
			if(dfs(i,now))ans++;			
		}

	}
	return ans;
}
int main()
{
//	freopen("attack.in","r",stdin);
//	freopen("attack.out","w",stdout);
	scanf("%d",&n);
	int x1;
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			scanf("%1d",&x1);
			a[i][j]=x1;tot+=(!x1);
			
			ju[i][j]=++tmp;ilegal[tmp]=x1;
		}
	}
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			if(a[i][j])continue;
			for(int k=1;k<=8;k++)
			{
				int yy=j+y[k];
				int xx=i+x[k];
				if(xx>0&&yy>0&&yy<=n&&xx<=n&&!a[xx][yy])
				{
					add(ju[i][j],ju[xx][yy]);
					add(ju[xx][yy],ju[i][j]);
				}
			}
		}
	}
	cout<<tot-xly()/2<<endl;//tot-xly()
	return 0;
}
/*
3
010
000
100
*/

T2 循环

点击查看代码
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int mod=100;
int x,a[100000000];
ll qpow(ll a,ll b)
{
	ll ans=1;
	while(b)
	{
		if(b&1)ans=1ll*ans*a%mod;
		b>>=1;
		a=1ll*a*a%mod;
	}
	return ans;
}
int main()
{
	ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
	freopen("number.in","r",stdin);
	freopen("number.out","w",stdout);
	cin>>x;
	map <int,int> mp;
	for(int j=1;;j++)
	{
		ll tmp=qpow(x,j);
		cout<<tmp<<" ";
		if(mp[tmp])
		{
			break;
		}
		mp[tmp]=1;
	}
	return 0;
}

T3 漫步

点击查看代码
#include <bits/stdc++.h>
#define lid st[rt].l
#define rid st[rt].r
#define ll long long
using namespace std;
const int N=1e5+5;
int n,MIN;
struct ac
{
	int d,v;
}a[N];
int main()
{
	ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
	freopen("jog.in","r",stdin);
	freopen("jog.out","w",stdout);
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i].d>>a[i].v;
	
	}
	int ans=0;
	MIN=INT_MAX;
	for(int i=n;i>=1;i--)
	{
		if(a[i].v<=MIN)
		{
			ans++;
			MIN=a[i].v;
		}
	}
	cout<<ans<<endl;
	return 0;
}
/*
5
0 1
1 2
2 3
3 2
6 1

*/

考试时想复杂了,其实不用权值线段树

点击查看代码
#include <bits/stdc++.h>
#define lid st[rt].l
#define rid st[rt].r
#define ll long long
using namespace std;
const int N=1e5+5;
int n,MAX,segtot,root[N];
struct ac
{
	int d,v;
}a[N];
struct tree
{
	int l,r,cnt,lz;
}st[N*35];
void pushup(int rt)
{
	st[rt].cnt=st[lid].cnt+st[rid].cnt;
}
void pushdown(int rt)
{
	if(st[rt].lz)
	{
		st[rt].lz=0;
		st[lid].lz=st[rid].lz=1;
		st[lid].cnt=st[rid].cnt=0;
	}
}
void update(int &rt,int l,int r,int pos,int val)
{
	if(!rt)rt=++segtot;
	if(l==r)
	{
		st[rt].cnt+=val;
		return;
	}
	int mid=(l+r)>>1;
	if(pos<=mid)update(lid,l,mid,pos,val);
	else update(rid,mid+1,r,pos,val);
	pushup(rt);
}
void del(int rt,int l,int r,int L,int R)
{
	if(L>R)return;
	if(!rt)return;
	if(L<=l&&r<=R)
	{
		st[rt].cnt=0;st[rt].lz=1;
		return;
	}
	pushdown(rt);
	int mid=(l+r)>>1;
	if(L<=mid)del(lid,l,mid,L,R);
	if(R>mid)del(rid,mid+1,r,L,R);
	pushup(rt);
}
int query(int rt,int l,int r,int L,int R)
{
	if(!rt)return 0;
	if(L<=l&&r<=R)
	{
		return st[rt].cnt;
	}
	int mid=(l+r)>>1;
	int ans=0;
	if(L<=mid)ans+=query(lid,l,mid,L,R);
	if(R>mid)ans+=query(rid,mid+1,r,L,R);	
	return ans;
}
int segtree(int ra,int rb)
{
	if(!ra)return rb;
	if(!rb)return ra;
	st[ra].cnt+=st[rb].cnt;
	st[ra].l=segtree(st[ra].l,st[rb].l);
	st[ra].r=segtree(st[rb].r,st[rb].r);
	return ra;
}
int main()
{
	ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
	freopen("jog.in","r",stdin);
	freopen("jog.out","w",stdout);
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i].d>>a[i].v;
		MAX=max(MAX,a[i].v);
		
	}
	update(root[n],1,MAX,a[n].v,1);
	for(int i=n-1;i>=1;i--)
	{
		
		if(query(root[n],1,MAX,1,a[i].v-1))
		{
			continue;
		}else 
		{
			update(root[i],1,MAX,a[i].v,1);
			root[n]=segtree(root[n],root[i]);
		}
	}
	cout<<query(root[n],1,MAX,1,MAX)<<endl;
	return 0;
}
/*
5
0 1
1 2
2 3
3 2
6 1

*/

T4 穿越

亚马逊雨林实在是太大了,小X和他的小弟们进去一会儿就迷路了,然而大雨已经来临,冲刷了一些道路,小X凭借他最后的5%的电量给你发来一条求助信息,希望你帮助他们逃出困境……
小X给你发来一张n×m的地图,每一个点有4种情况。
“0”:此地方可以走。
“1”:此地方不可以走。
“2”:此地方有一种凶恶的野兽。
“3”:此地方为传送地域。
野兽会不定时地苏醒过来,此阶段该处就不能走。
暴雨会不定时地冲刷一些地区,这些地区从今往后不可以行走,也不可以传送到。
传送地域之间可以互相传送,即可以从一个传送门传送到任何一个其他的传送门。
小X和他的小弟们现在位于(1,1),他们希望在(n,m)点逃出雨林。
他们只能前后左右移动,每移动一次需要花费1个单位的时间,传送一次需要花费2个单位的时间,也可以选择不传送。
注意:若下一秒某地区暴雨即将冲刷/野兽即将醒来,则不可以通行,也不可停留在这个这个地区。
在任意时刻,他们可以选择不进行任何操作。

输入

第一行两个整数n,m,表示一张n×m的地图。
接下来n行,每行m个整数,为0-3之间的一个数字。
接下来一行一个整数a,表示接下来a行描述暴雨情况。
接下来a行,每行第一个整数为t,表示此次暴雨在t时刻来临;第二个整数为p,表示此次暴雨冲刷了p个地区;接下来p组整数,每组有(x,y)两个整数,表示(x,y)这个地点被冲刷。(假设暴雨冲刷不需要时间,同一个地点可能被暴雨多次冲刷)
接下来b行,每行前两个整数为t1,t2,表示这个野兽在t1-t2时刻是苏醒的。接下来两个整数x,y,表示野兽位于x,y位置。(保证(x,y)=2)
不保证所有的野兽均会有苏醒的时刻
保证:(1,1)=(n,m)=0且永远不会被暴雨冲刷。

输出

一行一个整数,即最短逃脱时间。
(保证小X和他的小弟们可以逃脱亚马逊雨林)
最佳写法DP,循环时间,保证没有后效性

点击查看代码
#include <bits/stdc++.h>
#define ll long long
#define mk make_pair 
using namespace std;
const int N =305;
int n,m,g[N][N],a,b;
int X[6]={0,1,-1,0,0};
int Y[6]={0,0,0,1,-1};
struct Node
{
	int x,y,t;
};
int rain[N][N];vector<pair<int,int>> mons[N][N];
bool dp[10003][N][N];
vector <pair<int,int> > portal;
bool safe(int x,int y,int t)
{
	if(g[x][y]==1)return 0;
	if(rain[x][y]<=t)return 0;
	if(g[x][y]==2)
	{
		for(auto v:mons[x][y])
		{
			if(t<=v.second&&t>=v.first)
			{
				return 0;
			}
		}
	}
	return 1;
}
int main()
{
	freopen("cross.in","r",stdin);
	freopen("cross.out","w",stdout);
	cin>>n>>m;
	memset(rain,0x3f,sizeof rain);
//	memset(mons,0x3f,sizeof mons);	
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)
		{
			cin>>g[i][j];
			if(g[i][j]==3)
			{
				portal.push_back(mk(i,j));
			}
		}
	}
	cin>>a;
	int t,x,y,p;
	for(int i=1;i<=a;i++)
	{
		cin>>t;
		cin>>p;
		for(int j=1;j<=p;j++)
		{
			cin>>x>>y;
			if(!rain[x][y])
			{
				rain[x][y]=t;
			}else
			{
				rain[x][y]=min(t,rain[x][y]);
			}			
		}
	}
	cin>>b;
//	cout<<"**"<<endl;
	int t1,t2;
	for(int i=1;i<=b;i++)
	{
		cin>>t1>>t2;
		cin>>x>>y;
		mons[x][y].push_back(mk(t1,t2));
	}
	dp[0][1][1]=1;
	for(int t=0;t<=10000;t++)
	{
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=m;j++)
			{
				if(!dp[t][i][j])continue;
				if(i==n&&j==m)cout<<t<<endl,exit(0);
				for(int d=0;d<=4;d++)//include can't move
				{
					int xx=i+X[d],yy=j+Y[d];
					if(safe(xx,yy,t+1))dp[t+1][xx][yy]=1;
				}
				if(g[i][j]==3)
				{
					for(auto k:portal)
					{
						if(k.first==i&&k.second==j)
						{
							continue;
						}
						if(safe(k.first,k.second,t+2))dp[t+2][k.first][k.second]=1;
					}
				}
//				cout<<i<<" "<<j<<endl;
			}
		}
	}
	return 0;
}
/*
3 3
0 1 0
2 0 1
3 2 0
2
2 1 3 1
1 1 1 3
1
2 4 2 1
*/

考试时用的DP,不太对,还是用BFS最妙,照着题干一点一点来就好了

点击查看代码
#include <bits/stdc++.h>
#define ll long long
#define mk make_pair 
using namespace std;
const int N =305;
int n,m,g[N][N],a,b;
int x[6]={0,1,-1,0,0};
int y[6]={0,0,0,1,-1};
struct Node
{
	int x,y,t;
};
int rain[N][N];pair<int,int> mons[N][N];
int vis[N][N];
vector <pair<int,int> > portal;
void bfs()
{
	memset(vis,0x3f,sizeof vis);
	vis[1][1]=0;
	queue <Node> q;
	q.push({1,1});
	while(!q.empty())
	{
		int nx=q.front().x;
		int ny=q.front().y;
		q.pop();
		for(int i=1;i<=4;i++)
		{
			int xx=nx+x[i];
			int yy=ny+y[i];
			if(xx>0&&yy>0&&xx<=n&&yy<=m)
			{
				if(g[xx][yy]==1)continue;
				else if(g[xx][yy]==0)
				{
					if(vis[nx][ny]+1<rain[xx][yy]&&vis[nx][ny]+1<vis[xx][yy])
					{
						vis[xx][yy]=vis[nx][ny]+1;
						q.push({xx,yy});
					}
				}else if(g[xx][yy]==2)
				{
					if(vis[nx][ny]+1< rain[xx][yy])
					{
						if(vis[nx][ny]+1>=mons[xx][yy].first&&vis[nx][ny]+1<=mons[xx][yy].second)
						{
							if(mons[xx][yy].second+1<rain[xx][yy]&&mons[xx][yy].second+1<vis[xx][yy])
							{
								vis[xx][yy]=mons[xx][yy].second+1;
								q.push({xx,yy});
							}				
						}
						else
						{
							if(vis[nx][ny]+1<vis[xx][yy])
							{
								vis[xx][yy]=vis[nx][ny]+1;
								q.push({xx,yy});
							}					
						}						
					}

				}else if(g[xx][yy]==3)
				{
					if(vis[nx][ny]+1<rain[xx][yy]&&vis[nx][ny]+1<vis[xx][yy])
					{
						vis[xx][yy]=vis[nx][ny]+1;
						q.push({xx,yy});
					}
					if(vis[nx][ny]+1<rain[xx][yy])
					{
						for(auto id:portal)
						{
							int Px=id.first,Py=id.second;
							if(vis[nx][ny]+3<rain[Px][Py]&&vis[nx][ny]+3<vis[Px][Py])
							{
								vis[Px][Py]=vis[nx][ny]+3;
								q.push({Px,Py});
							}
						}
					}
				}
			}
		}
	}
}
int main()
{
	freopen("cross.in","r",stdin);
	freopen("cross.out","w",stdout);
	cin>>n>>m;
	memset(rain,0x3f,sizeof rain);
//	memset(mons,0x3f,sizeof mons);	
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)
		{
			cin>>g[i][j];
			if(g[i][j]==3)
			{
				portal.push_back(mk(i,j));
			}
		}
	}
	cin>>a;
	int t,x,y,p;
	for(int i=1;i<=a;i++)
	{
		cin>>t;
		cin>>p;
		for(int j=1;j<=p;j++)
		{
			cin>>x>>y;
			if(!rain[x][y])
			{
				rain[x][y]=t;
			}else
			{
				rain[x][y]=min(t,rain[x][y]);
			}			
		}
	}
	cin>>b;
	int t1,t2;
	for(int i=1;i<=b;i++)
	{
		cin>>t1>>t2;
		cin>>x>>y;
		mons[x][y]=(mk(t1,t2));
	}
	bfs();
	cout<<vis[n][m]<<endl;
	return 0;
}
/*
3 3
0 1 0
2 0 1
3 2 0
2
2 1 3 1
1 1 1 3
1
2 4 2 1
*/

还可以用DP实现,并且还挺快的

点击查看代码
#include <bits/stdc++.h>
#define ll long long
#define mk make_pair 
using namespace std;
const int N =505,INF=0x3f3f3f3f;
int n,m,g[N][N],a,b;
int rain[N][N];pair<int,int> mons[N][N];
int dp[N][N];
vector <pair<int,int> > portal;
void ddp()
{
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)
		{
			if(i==1&&j==1)continue;//attention
			if(g[i][j]==3)
			{
				dp[i][j]=min({dp[i-1][j]+1,dp[i][j-1]+1,dp[i+1][j]+1,dp[i][j+1]+1,dp[i][j]});
				for(int k=0;k<portal.size();k++)
				{
					int xx=portal[k].first,yy=portal[k].second;
					dp[i][j]=min(dp[xx][yy]+2,dp[i][j]);
				}
				if(dp[i][j]>=rain[i][j]&&rain[i][j]!=INF)
				{
					dp[i][j]=INF;
				}
			}else if(g[i][j]==0)
			{
				dp[i][j]=min({dp[i-1][j]+1,dp[i][j-1]+1,dp[i+1][j]+1,dp[i][j+1]+1,dp[i][j]});
				if(dp[i][j]>=rain[i][j]&&rain[i][j]!=INF)
				{
					dp[i][j]=INF;
				}					
			}else if(g[i][j]==2)
			{
				dp[i][j]=min({dp[i-1][j]+1,dp[i][j-1]+1,dp[i+1][j]+1,dp[i][j+1]+1,dp[i][j]});
				if(mons[i][j].first!=0)
				if(dp[i][j]>=mons[i][j].first&&dp[i][j]<=mons[i][j].second)
				{
					if(mons[i][j].second+1<rain[i][j]&&rain[i][j]!=0)//注意这里不用比较mons[i][j].second+1与dp[i][j]的大小(血的教训),因为不得不选
					{
						dp[i][j]=mons[i][j].second+1;
					}
				}
				if(dp[i][j]>=rain[i][j]&&rain[i][j]!=0)
				{
					dp[i][j]=INF;
					continue;
				}
			}

//			cout<<i<<" "<<j<<" "<<dp[i][j]<<endl;
		}
	}
}
int main()
{
	freopen("cross.in","r",stdin);
	freopen("cross.out","w",stdout);
	cin>>n>>m;
	memset(rain,0x3f,sizeof rain);
	memset(dp,0x3f,sizeof dp);
//	memset(mons,0x3f,sizeof mons);	
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)
		{
			cin>>g[i][j];
			if(g[i][j]==3)
			{
				portal.push_back(mk(i,j));
			}
		}
	}
	cin>>a;
	int t,x,y,p;
	for(int i=1;i<=a;i++)
	{
		cin>>t;
		cin>>p;
		for(int j=1;j<=p;j++)
		{
			cin>>x>>y;
			rain[x][y]=min(t,rain[x][y]);			
		}
	}
	cin>>b;
	int t1,t2;
	for(int i=1;i<=b;i++)
	{
		cin>>t1>>t2;
		cin>>x>>y;
		mons[x][y]=(mk(t1,t2));
	}
//	for(int i=1;i<=2;i++)
	dp[1][1]=0;
	for(int i=1;i<=2;i++)ddp();
	cout<<dp[n][m]<<endl;
	return 0;
}
/*
3 3
0 1 0
2 0 1
3 2 0
2
2 1 3 1
1 1 1 3
1
2 4 2 1
*/

T5. 结队

要用并查集
但我可以用数组模拟

点击查看代码
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N =5e4+5;
int a,b,p;
bool ispri[N];int prim[N],tot;
void get(int n)
{
	ispri[1]=1;
	for(int i=2;i<=n;i++)
	{
		if(!ispri[i])
		{
			prim[++tot]=i;
		}
		for(int j=1;j<=tot;j++)
		{
			if(prim[j]*i>n)break;
			ispri[prim[j]*i]=1;
			if(i%prim[j]==0)break;
		}
	}
}
set <int> zu[N];
vector <int> he[N];bool vis[N];
int pos,unok,ans;
void fen(int x)
{
	bool flag=0;
	for(int i=pos;i<=tot;i++)
	{
		if(x<prim[i])break;
		if(x%prim[i]==0&&prim[i]>=p)
		{
			flag=1;
			zu[prim[i]].insert(x);
			he[x].push_back(prim[i]);
		}
	}
	if(!flag)
	{
		vis[x]=1;
		ans++;
//		cout<<he[x].size()<<endl;
	}
}
int havn[N];
int main()
{
	ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
	freopen("merge.in","r",stdin);
	freopen("merge.out","w",stdout);
	cin>>a>>b>>p;
	get(b);
	pos=lower_bound(prim+1,prim+tot,p)-prim;
	for(int i=a;i<=b;i++)
	{
		fen(i);
	}
	int now=0;
	for(int su=a;su<=b;su++)
	{
		int zuhao=INT_MAX;bool is=0;
		for(auto j:he[su])
		{
//			cout<<j<<endl;
			if(havn[j])
			{
				zuhao=min(zuhao,havn[j]);
				is=1;
			}
		}
		if(!is)
		{
			now++;
			for(auto j:he[su])havn[j]=now;
		}else 
			for(auto j:he[su])havn[j]=zuhao;
	}
//	for(int i=pos;i<=tot;i++)
//	{
//		cout<<prim[i]<<" "<<havn[prim[i]]<<endl;
//	}
	now=0;
	memset(vis,0,sizeof(vis));
	for(int i=pos;i<=tot;i++)
	{
		int su=prim[i];
		if(!vis[havn[su]])
		{
			vis[havn[su]]=1;
			now++;
		}
	}
	cout<<ans+now;
	return 0;
}
/*
10 20 3
*/
用并查集优化会快很多
点击查看代码
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N =5e4+5;
int a,b,p;
bool ispri[N];int prim[N],tot;
int fa[N];
int find(int x)
{
	if(fa[x]!=x)
	{
		fa[x]=find(fa[x]);
	}
	return fa[x];
}
void get(int n)
{
	ispri[1]=1;
	for(int i=2;i<=n;i++)
	{
		if(!ispri[i])
		{
			prim[++tot]=i;
		}
		for(int j=1;j<=tot;j++)
		{
			if(prim[j]*i>n)break;
			ispri[prim[j]*i]=1;
			if(i%prim[j]==0)break;
		}
	}
}
vector <int> he[N];
int pos,R,ans;
void fen(int x)
{
	bool flag=0;
	for(int i=pos;i<=tot;i++)
	{
		if(x<prim[i])break;
		if(x%prim[i]==0&&prim[i]>=p)
		{
			flag=1;
			R=max(R,i);
			he[x].push_back(prim[i]);
		}
	}
	if(!flag)
	{
		ans++;
//		cout<<he[x].size()<<endl;
	}
}
int havn[N];
unordered_map<int,bool> mp;
int main()
{
	ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
	freopen("merge.in","r",stdin);
	freopen("merge.out","w",stdout);
	cin>>a>>b>>p;
	get(b);
	pos=lower_bound(prim+1,prim+tot,p)-prim;
	int now=0;
	for(int i=1;i<=b;i++)fa[i]=i;//这里按道理来说应该为a/prim[i]*prime[i]>=p 
	for(int i=pos;i<=tot;i++)
	{
		int x=find(prim[i]);
		for(int j=a/prim[i];j*prim[i]<=b;j++)
		{
			if(j*prim[i]<a)j++;
			int y=find(j*prim[i]);
			if(x!=y)fa[y]=x;
		}
	}
	for(int i=a;i<=b;i++)
	{
		int f=find(i);
		if(!mp[f]) mp[f]=1,ans++;
	}
	cout<<ans;
	return 0;
}
/*
10 20 3
*/
/*
10 20 3
*/
posted @ 2024-05-13 15:43  wlesq  阅读(32)  评论(2编辑  收藏  举报