• [NOI2016]循环之美


    题意

    牛牛是一个热爱算法设计的高中生。在他设计的算法中,常常会使用带小数的数进行计算。牛牛认为,如果在 (k) 进制下,一个数的小数部分是纯循环的,那么它就是美的。现在,牛牛想知道:对于已知的十进制数 (n)(m),在 (k) 进制下,有多少个数值上互不相等的纯循环小数,可以用分数 (frac xy) 表示,其中 (1≤x≤n,1≤y≤m),且 (x,y)是整数。一个数是纯循环的,当且仅当其可以写成以下形式:

    (a.dot{c_1} c_2 c_3 dots c_{p - 1} dot{c_p})

    其中,(a) 是一个整数,(p≥1);对于 (1≤i≤p)(c_i)(k) 进制下的一位数字。

    例如,在十进制下,(0.45454545……=0.dot {4} dot {5})是纯循环的,它可以用 (frac {5}{11})(frac{10}{22}) 等分数表示;在十进制下,(0.1666666……=0.1dot6)则不是纯循环的,它可以用 (1/6) 等分数表示。需要特别注意的是,我们认为一个整数是纯循环的,因为它的小数部分可以表示成 (0) 的循环或是 (k-1) 的循环;而一个小数部分非 (0) 的有限小数不是纯循环的。

    输入输出格式

    输入格式:

    只有一行,包含三个十进制数N,M,K意义如题所述,保证 1≤n≤109,1≤m≤109,2≤k≤2000

    输出格式:

    一行一个整数,表示满足条件的美的数的个数。

    输入输出样例

    输入样例#1:

    2 6 10

    输出样例#1:

    4

    题解

    自闭==
    好难啊,推了半天实在不会推式子的前半部分的那些东西
    题目就是让求(sum_{i=1}^{n}sum_{j=1}^{m}{[gcd(i,j)=1][gcd(j,k)=1]})
    (sum_{i=1}^{n}sum_{j=1}^{m}{[gcd(i,j)=1][gcd(j,k)=1]})
    先考虑前面的(sum_{i=1}^{n}sum_{j=1}^{m}{[gcd(i,j)=1]})
    很显然是(sum_{d=1}^{n}{mu(d)frac{n}{d}frac{m}{d}})
    那现在式子就成了(sum_{d=1}^{n}{mu(d)frac{n}{d}}sum_{i=1}^{m/d}{[gcd(id,k)=1]})
    这样的话(d)就必须满足(gcd(d,k)=1)
    所以(sum_{d=1}^{n}{[gcd(d,k)=1]mu(d)frac{n}{d}}sum_{i=1}^{m/d}{[gcd(i,k)=1]})
    先看后面的那一部分:
    如果(frac{m}{d} | k)
    那么答案就是(frac{m}{dk}phi(k))
    对于剩下的那(frac{m}{d} \% k)的部分
    我们暴力预处理出来就行了
    所以后面的部分等于(frac{m}{dk}phi(k)+F(frac{m}{d} \% k))
    这么一看我们只需要再求出一个(S(n,k)=sum_{d=1}^{n}{[gcd(d,k)=1]mu(d)})就行了
    但是由于有一个限制,所以并不好筛
    (sum_{d=1}^{n}{[gcd(d,k)=1]mu(d)}\=sum_{d=1}^{n}{mu(d)}sum_{t|gcd(d,k)}{mu(t)}\=sum_{d=1}^{n}{mu(d)}sum_{t|d,t|k}{mu(t)})
    由于需要(t|d,t|k),所以(t<=k),所以满足条件的(d)一定是(d|k)
    (\=sum_{d|k}{mu(d)}sum_{t|d}{mu(t)})
    (=sum_{d|k}{mu(d)}sum_{t=1}^{n/d}{mu(dt)})
    (mu(dt))不为0的话必须要满足(gcd(d,t)=1)
    (=sum_{d|k}{mu(d)}sum_{t=1,gcd(d,t)=1}^{n/d}{mu(d)mu(t)}\=sum_{d|k}{mu(d)^2}sum_{t=1,gcd(d,t)=1}^{n/d}{mu(t)}\=sum_{d|k}{mu(d)^2}S(frac{n}{d},d))
    这样就可以杜教筛+记搜了
    只有(d=1)的时候才计算(summu),否则就枚举因数继续计算

    代码

    #include<map>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    # define MP(x , y) (make_pair(x , y))
    # define LL long long
    const int M = 4000005 ;
    
    using namespace std ;
    
    bool notp[M] ;
    int p[M] , pnum , mu[M] ;
    LL n , m , k , upp = 4000000 ;
    LL sum[M] , f[M] , ans ;
    map < pair < LL , LL > , LL > pi ;
    inline int gcd(int a , int b) {
    	if(b == 0) return a ;
    	return gcd(b , a % b) ;
    }
    inline void presolve(int n) {
    	sum[1] = 1 ;
    	for(int i = 2 ; i <= n ; i ++) {
    		if(!notp[i]) {
    			p[++pnum] = i ;
    			sum[i] = -1 ;
    		}
    		for(int j = 1 ; j <= pnum && 1LL * i * p[j] <= n ; j ++) {
    			notp[i * p[j]] = true ;
    			if(i % p[j] == 0) {
    				sum[i * p[j]] = 0 ;
    				break ;
    			}
    			else sum[i * p[j]] = - sum[i] ;
    		}
    	}
    	for(int i = 1 ; i <= n ; i ++) {
    		mu[i] = sum[i] ;
    		sum[i] = sum[i - 1] + sum[i] ;
    	}
    	for(int i = 1 ; i <= k ; i ++) 
    		f[i] = f[i - 1] + (gcd(i , k) == 1) ;
    }
    
    inline LL F(LL n) { 
    	return f[k] * (n / k) + f[n % k] ;
    }
    
    inline LL Sum(LL n , LL k) {
    	if(n == 0) return 0 ;
    	if(k == 1 && n <= upp) return sum[n] ;
    	if(pi[MP(n , k)]) return pi[MP(n , k)] ;
    	LL ret = 0 ;
    	if(k == 1) {
    		ret = 1 ;
    		for(LL l = 2 , r ; l <= n ; l = r + 1) {
    			r = n / (n / l) ;
    			ret -= (r - l + 1) * Sum(n / l , k) ;
    		}
    	}
    	else {
    		for(int x = 1 , y ; x * x <= k ; x ++) {
    			if(k % x) continue ;
    			if(mu[x]) 
    				ret += Sum(n / x , x) ;
    			y = k / x ;
    			if(x == y) continue ;
    			if(mu[y]) 
    				ret += Sum(n / y , y) ;
    		}
    	}
    	pi[MP(n , k)] = ret ;
    	return ret ;
    }
    int main() {
    	scanf("%lld%lld%lld",&n,&m,&k) ;
    	presolve(4000000) ;
    	for(LL l = 1 , r ; l <= min(n , m) ; l = r + 1) {
    		r = min(n / (n / l) , m / (m / l)) ;
    		ans += (Sum(r , k) - Sum(l - 1 , k)) * (n / l) * F(m / l) ;
    	}
    	printf("%lld
    ",ans) ;
    	return 0 ;
    }
    
  • 相关阅读:
    Java集合概述
    Java8内存结构—永久代(PermGen)和元空间(Metaspace)
    ArrayList分析
    “三次握手,四次挥手”你真的懂吗?
    Object中的方法以及对象相等的判定
    笔记
    Mybatis中的@Param注解
    react与jQuery对比,有空的时候再翻译一下
    队列理论和队列网络模型 queueing theory and queueing network model
    下拉列表autocomplete各种实现方式比较
  • 原文地址:https://www.cnblogs.com/beretty/p/10435010.html
Copyright © 2020-2023  润新知