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;
    }
    

      

  • 相关阅读:
    A Simple Problem with Integers poj 3468 多树状数组解决区间修改问题。
    Fliptile 开关问题 poj 3279
    Face The Right Way 一道不错的尺取法和标记法题目。 poj 3276
    Aggressive cows 二分不仅仅是查找
    Cable master(二分题 注意精度)
    B. Pasha and String
    Intervals poj 1201 差分约束系统
    UITextField的快速基本使用代码块
    将UIImage转换成圆形图片image
    color转成image对象
  • 原文地址:https://www.cnblogs.com/zhouzhendong/p/CF542D.html
Copyright © 2011-2022 走看看