zoukankan      html  css  js  c++  java
  • JLOI2014 聪明的燕姿【搜索-细节】

    题目链接

    题目解析

    两个公式:

    整数唯一分解定理:

    (n=prod_{i=1}^mp_i^{α_i})

    约数和定理:

    (S=prod_{i=1}^msum_{j=0}^{α_i}p_i^j)

    然后可以搜索质因子和它们的指数,记录下当前还剩多少和(s),已经枚举到的第(i)个质数,目前产生的答案(x)

    需要剪枝:若(p^2>=S),有(frac{s}{p+1}<p),而我们又是递增枚举这个(p)的,所以后面就不用枚举了,这个一定不合法(那么所提到的这个答案在(frac{s}{p+1})就已经算过了(因为从小到大))

    除非它是最后一个,后面没有数,也就是(p+1==s),那么这种情况可以特判:

    如果(s-1)是质数,并且比上一次枚举到的质因子大,那么就把((s-1) imes x)也算入答案。

    这道题输出调了我好久(见注释,果然是太菜了嘛(qwq)

    虽然我没有燕姿那么聪明,但是希望我也能找到自己等的人叭,不需要所有,有就够了。


    ►Code View

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<vector>
    #include<queue>
    using namespace std;
    #define LL long long
    #define N 100005
    #define INF 0x3f3f3f3f
    int rd()
    {
    	int x=0,f=1;char c=getchar();
    	while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();}
    	while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+(c^48); c=getchar();}
    	return f*x;
    }
    int prim[N],pn;
    bool vis[N];
    int ans[N],cnt;
    void Sieve()
    {
    	for(int i=2;i<N;i++)
    	{
    		if(!vis[i]) prim[++pn]=i;
    		for(int j=1;j<=pn&&prim[j]*i<N;j++)
    		{
    			vis[i*prim[j]]=1;
    			if(i%prim[j]==0) break;
    		}
    	}
    }
    bool check(int x)
    {
    	if(x==1) return 0;
    	for(int i=1;prim[i]*prim[i]<=x;i++)
    		if(x%prim[i]==0) return 0;
    	return 1;
    }
    void dfs(int now,int i,int x)
    {//还剩多少没有分解 第几个质数 当前答案 
    	if(now==1)
    	{
    		ans[++cnt]=x;
    		return ;
    	}
    	if(check(now-1)&&now-1>prim[i]) ans[++cnt]=(now-1)*x;//sum-1是满足条件的一个质因子
    	for(int j=i+1;prim[j]*prim[j]<=now;j++)
    	{//枚举质因子 
    		int sum=1+prim[j],lst=prim[j];
    		while(sum<=now)
    		{
    			if(now%sum==0) dfs(now/sum,j,x*lst);
    			lst*=prim[j],sum+=lst;
    		}
    	}
    }
    int main()
    {
    	Sieve();
    	int s;
    	while(scanf("%d",&s)!=EOF)
    	{
    		cnt=0;
    		dfs(s,0,1);
    		sort(ans+1,ans+cnt+1);
    		printf("%d
    ",cnt);
    		for(int i=1;i<=cnt;i++)
    			printf("%d ",ans[i]);
    		if(cnt) puts("");//Cao 注意格式啊 如果没有数 那么就没有这个换行 也不能这么打(见下 
    		/*
    		for(int i=1;i<cnt;i++)
    			printf("%d ",ans[i]);
    		printf("%d
    ,ans[cnt]);
    		因为不知道cnt有没有 如果cnt==0 就会多输出一个ans[0]啊 
    		*/ 
    	} 
    	return 0;
    } 
    
  • 相关阅读:
    【windows 10 安装docker for windows】
    【windows本地修改git账号、路径信息】
    【echarts】简单使用流程(java)
    【MySql】explain
    【thymeleaf-标签】th:with
    【MongoDB】Windows:安装与启动
    【thymeleaf-标签】th:if
    Thread类中interrupt()、interrupted()和isInterrupted()方法详解
    java中的锁
    LinkedList集合详解
  • 原文地址:https://www.cnblogs.com/lyttt/p/14004843.html
Copyright © 2011-2022 走看看