时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld
题目描述
珂朵莉想求:
第x小的正整数v使得其最小的质因数为质数y,即正好有x-1个[1,v-1]之内的正整数满足其最小的质因数为质数y。
若答案超过1000000000则输出0。
输入描述:
第一行两个正整数x,y
输出描述:
输出一个整数表示答案
示例1
输入
2 3
输出
9
示例2
输入
21000000 11
输出
0
示例3
输入
1500 13
输出
93769
说明
3最小的质因数为3
9最小的质因数为3
第2小的最小质因数为3的数就是9
备注:
对于100%的数据,1 <= x,y <= 1000000000
#include<cstdio> #include<cstring> #include<bitset> #include<algorithm> using namespace std; long long N=1e9,x,y,ans; long long p[18]={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61};//18 bitset<20000000>ok; void solve1(){ int now=0; for(int i=2;i<y;i++) if(!ok[i])for(int j=i;j<=N;j+=i) ok[j]=1; for(int i=1;i<N;++i) if(!ok[i]) { ++now; if(now==x) {ans=i;break;} } return; } long long cal(long long a,long long ord){ if(p[ord]>=y) return a; if(!a) return 0; return cal(a,ord+1)-cal(a/p[ord],ord+1); } void solve2(){ long long l=1,r=N; while(r>=l) { long long mid=(l+r)>>1; if(cal(mid,0)>=x) r=mid-1,ans=mid; else l=mid+1; } } int main(){ scanf("%lld%lld",&x,&y); N/=y; if(y>61) solve1(); else solve2(); printf("%lld\n",y*ans); }
当p>=x时,可以用1e9/x的筛算出来答案
当p<x时,考虑二分答案ans,然后容斥即可验证
x在60左右的时候最快
题目描述
珂朵莉给你一个无向图
其有n个点,m条边
对于每条边,她想知道删了这条边之后这个图是不是一个二分图
输入描述:
第一行两个整数n,m
之后m行,每行两个数x,y表示有一条x和y之间的无向边
第i个边的序号即为i
输出描述:
第一行输出一个整数,表示有多少边满足条件
接下来一行,从小到大输出这些边的序号
如果没有边满足条件,只输出一行一个数0,注意不要多输出换行
示例1
输入
4 4 1 2 1 3 2 4 3 4
输出
4 1 2 3 4
说明
对于100%的数据,有n , m<=1000000
备注:
对于100%的数据,有n , m<=1000000
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N=2e6+88; bool vis[N]; int n,m,cnt,ans[N]; int head[N],tot=2,top; int bian[N<<1],f[N],g[N],pos[N]; struct node{ int to,next; }e[N<<1]; void add(int u,int v){ e[tot].to=v;e[tot].next=head[u];head[u]=tot++; } void dfs(int c,int et){ vis[c]=1; pos[c]=++top; for(int i=head[c];i;i=e[i].next){ if(bian[i]==-1) continue; if(!vis[e[i].to]) { bian[i]=bian[i^1]=-1; dfs(e[i].to,i>>1); f[et]+=f[i>>1]; g[et]+=g[i>>1]; } else { if(bian[i]==1) --f[et]; if(bian[i]==2) --g[et]; if(bian[i]==0) { if((pos[c]-pos[e[i].to])&1) ++g[et],bian[i]=bian[i^1]=2; else ++f[et],++cnt,bian[i]=bian[i^1]=1; } } } --top; } int main(){ scanf("%d%d",&n,&m); for(int i=1,x,y;i<=m;++i) { scanf("%d%d",&x,&y); add(x,y); add(y,x); } for(int i=1;i<=n;++i) if(!vis[i]) dfs(i,0); int sum=0; if(!cnt) for(int i=1;i<=m;++i) ans[sum++]=i; else { for(int i=1;i<=m;++i) if(f[i]==cnt&&g[i]==0) ans[sum++]=i; else if(cnt==1&&bian[i<<1]==1) ans[sum++]=i; } printf("%d\n",sum); for(int i=0;i<sum;++i) printf("%d%c",ans[i],i==sum-1?‘\n‘:‘ ‘); }
二分图即不能有奇环的无向图
要使得所有的奇环消失,即要删去所有奇环的交上的边。
但是如果删去奇环和偶环的交上的边,奇环和偶环就会重新组成一个新的奇环,所以在偶环上的边是不能删的。
先随便搞个生成树出来,然后对于每个非树边在树上打标记,最后DFS一次即可以实现O( n + m )