zoukankan      html  css  js  c++  java
  • Codeforces 542D Superhero's Job 数论 哈希表 搜索

    原文链接https://www.cnblogs.com/zhouzhendong/p/CF542D.html

    题目传送门 - CF542D

    题目传送门 - 51Nod1477

    题意

      定义公式 $J(x) = sum_{1 leq k leq x 且 k|x 且 gcd (k,x/k) = 1} k$ 。

      现在给定一个整数 $A$ ,要求有多少正整数 $x$ ,满足 $J(x)=A$ 。

      $x|n$ 表示 $x$ 是 $n$ 的因子。

      $gcd(a,b) 表示 $a$ 和 $b$ 的最大公约数。

      $1leq Aleq 10^{12}$

    题解

      先考虑如何求 $J(x)$ 。

      由于 $gcd(k,x/k)=1$ ,所以选出来的 $x$ 和 $x/k$ 的质因数集合没有交集。

      故如果设 $x=prod p_i^{a_i}$ ,那么 $J(x) = prod (p_i^{a_i}+1)$ 。

      于是我们考虑 dfs 枚举 A 的因数分解方式,加一些剪枝和优化就可以过了。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    LL read(){
    	LL x=0;
    	char ch=getchar();
    	while (!isdigit(ch))
    		ch=getchar();
    	while (isdigit(ch))
    		x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    	return x;
    }
    const int N=1000005;
    LL n;
    struct hash_map{
        static const int Ti=233,mod=1<<21;
        int cnt,nxt[mod+1],fst[mod+1];
        LL k[mod+1],v[mod+1];
        int Hash(LL x){
            int v=x&(mod-1);
            return v==0?mod:v;    
        }
        void clear(){
            cnt=0;
            memset(fst,0,sizeof fst);
        }
        LL &operator [] (LL x){
            int y=Hash(x);
            for (int p=fst[y];p;p=nxt[p])
                if (k[p]==x)
                    return v[p];
            k[++cnt]=x,nxt[cnt]=fst[y],fst[y]=cnt;
            return v[cnt]=0;
        }
    }check,use;
    LL prime[N],pcnt,vis[N];
    void get_prime(){
    	memset(vis,0,sizeof vis);
    	pcnt=0;
    	for (int i=2;i<N;i++){
    		if (vis[i])
    			continue;
    		prime[++pcnt]=i;
    		for (int j=i+i;j<N;j+=i)
    			vis[j]=1;
    	}
    }
    int Check(LL x){
    	if (x<=1)
    		return 0;
    	for (int i=1;prime[i]*prime[i]<=x&&i<=pcnt;i++)
    		if (x%prime[i]==0){
    			while (x%prime[i]==0)
    				x/=prime[i];
    			return x==1?prime[i]:0;
    		}
    	return x;
    }
    LL ans=0;
    LL fac[N*2],fc=0;
    void dfs(LL n,LL *d){
    	if (*d>n)
    		return;
    	if (check[n]&&!use[check[n]])
    		ans++;
    	if (*d>=n/ *d)
    		return;
    	for (;*d<n/ *d;d++){
    		if (n%*d)
    			continue;
    		LL &v=use[check[*d]];
    		if (!v)
    			v=1,dfs(n/ *d,d+1),v=0;
    	}
    }
    int main(){
    	get_prime();
    	n=read();
    	if (n==1)
    		return puts("1"),0;
    	check.clear();
    	for (LL i=1;i*i<=n;i++){
    		if (n%i)
    			continue;
    		LL j=n/i;
    		check[i]=Check(i-1);
    		check[j]=Check(j-1);
    		if (check[i])
    			fac[fc++]=i;
    		if (i!=j&&check[j])
    			fac[fc++]=j;
    	}
    	use.clear();
    	sort(fac,fac+fc);
    	fac[fc]=n+1;
    	dfs(n,fac);
    	printf("%lld",ans);
    	return 0;
    }
    

      

  • 相关阅读:
    js数组
    关于编程,程序员的一些语录
    css心得
    js函数
    一些电脑基础知识
    gnome3安装
    C学习小记
    ubuntu重装系统后
    elinks文字浏览器
    快捷方式
  • 原文地址:https://www.cnblogs.com/zhouzhendong/p/CF542D.html
Copyright © 2011-2022 走看看