[codeforces920G] 容斥+二分

题意:求出与p互质并且大于x的第k个数

思路:首先我们可以求出p的所有质因子,可以根据a/b表示[1,a]中以b为因子的数的个数,然后用这个通过容斥来求得[1,a]中与与p互质的数的个数,然后就可以愉快地二分了。

import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.StreamTokenizer;
import java.math.BigInteger;
import java.util.ArrayList;
import java.io.BufferedReader;
import java.io.InputStreamReader;



public class Main {
    public static void main(String[] args) throws IOException {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader sc = new InputReader(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        Task solver = new Task();
        solver.solve(1, sc, out);
        out.close();
    }

    static class Task {
    	public int getCnt(int x,ArrayList<Integer> factor) {    //二进制枚举容斥
    		int ans=x;
    		
    		for(int i=1;i<(1<<(factor.size()));i++) {
    			int cnt=0;
    			int temp=1;
    			for(int j=0;j<factor.size();j++) {
    				if((i&(1<<j))!=0) {
    					temp*=factor.get(j);
    					cnt++;
    				}
    			}
    			if(cnt%2==1)               //注意符号
    				ans-=x/temp;
    			else
    				ans+=x/temp;
    		}
    		
    		return ans;
    	}
    	
    	public boolean check(int x,int k,int preCnt,ArrayList<Integer> factor) {
    		return getCnt(x,factor)-preCnt>=k;
    	}
    	
        public void solve(int testNumber, InputReader sc, PrintWriter out) throws IOException {
        	ArrayList<Integer> factor=new ArrayList<Integer>();
        	int T=sc.nextInt();
        	
        	while(T-->0) {
        		factor.clear();
        		int x=sc.nextInt();
        		int p=sc.nextInt();
        		int k=sc.nextInt();
        		
        		
        		for(int i=2;i*i<=p;i++) {
        			if(p%i==0)
        				factor.add(i);
        			while(p%i==0)
        				p/=i;
        		}
        		if(p!=1)
        			factor.add(p);
        		
        		int preCnt=getCnt(x,factor);
        		int l=x+1;
        		int r=(int) 1e7;
        		int ans=-1;
        		while(l<=r) {
        			int mid=(l+r)>>1;
        		    if(check(mid,k,preCnt,factor)) {
        		    	r=mid-1;
        		    	ans=mid;
        		    }
        		    else
        		    	l=mid+1;
        		}
        		out.println(ans);
        	}
        }
    }

    static class InputReader{
        StreamTokenizer tokenizer;
        public InputReader(InputStream stream){
            tokenizer=new StreamTokenizer(new BufferedReader(new InputStreamReader(stream)));
            tokenizer.ordinaryChars(33,126);
            tokenizer.wordChars(33,126);
        }
        public String next() throws IOException {
            tokenizer.nextToken();
            return tokenizer.sval;
        }
        public int nextInt() throws IOException {
            return Integer.parseInt(next());
        }
        public long nextLong() throws IOException {
            return Long.parseLong(next());
        }
        public boolean hasNext() throws IOException {
            int res=tokenizer.nextToken();
            tokenizer.pushBack();
            return res!=tokenizer.TT_EOF;
        }
        
        public double nextDouble() throws NumberFormatException, IOException {
        	return Double.parseDouble(next());
        }
        
        public BigInteger nextBigInteger() throws IOException {
        	return new BigInteger(next());
        }
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值