【比赛】高一下三调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
*/