zoukankan      html  css  js  c++  java
  • [CF1499D]The Number of Pairs 数学

    D. The Number of Pairs

    题意

    给你(c, d, x),求满足(c cdot lcm(a, b) - d cdot gcd(a, b) = x)的点对((a, b))的个数。
    (T)组数据
    (T <= 10^4), (c, d, x <= 10^7)

    题解

    为了表示简单一点,令(l = lcm(a, b), g = gcd(a, b))
    (cl - dg = x)
    由一些常识,我们知道(lcm(a, b) cdot gcd(a, b) = a cdot b)
    所以(l = frac{ab}{g})
    ( herefore frac{cab}{g} - dg = x)
    因为(g)(gcd(a, b)),所以可设(a = kg, b = tg)
    代回原式

    [cktg - dg = x ]

    [g = frac{x}{ckt - d} ]

    因为(g)是整数,所以(ckt - d)(x)的因子
    所以我们枚举(i = ckt - d)
    易知对于一个已知的(g)而言,((k, t))((a, b))是一一对应的关系
    所以我们要统计((a, b))相当于统计((k, t))
    又因为(gcd(a, b))是最大公约数,所以(k, t)必互质,否则就可以将(gcd(k, t))加入(gcd(a, b))使其变得更大

    [ecause i = ckt - d ]

    [ herefore kt = frac{i + d}{c} ]

    当我们枚举(i)时,(frac{i + d}{c})为常量
    所以我们就是对于一个常量找互质的数对((k, t))使其满足数对乘积等于这个常量
    相当于对这个常量质因数分解,把分解出来的质因数分成两份,找合法的分配方案数
    (frac{i + d}{c} = prod_{j<=m}{p_j^{f_j}}), (m)(frac{i + d}{c})的质因数种数,(f_j)表示(p_j)这个质因数有(f_j)
    那么因为分出来的两部分互质,所以对于一个质因数(p_j)要么全给(k)要么全给(t)
    所以由一些数学常识(对于每个质因数要么选要么不选),我们可以知道,方案数为(2^m)
    所以((k, t))的对数就是(sum_{i | k}{2^{m(i)}})
    对于每组询问,我们暴力枚举(x)的因子(i), 对于每个(i),我们找出(frac{i + d}{c})对应的质因数种数(m(frac{i + d}{c}))
    统计一下(sum{2^{m(frac{i + d}{c})}})就是答案
    估计一下,因子(i)最多log个,(m(frac{i + d}{c}) <= log (frac{i + d}{c}))
    (sum{2^{m(frac{i + d}{c})}})大概不会超过(frac{i + d}{c} cdot i)个,也就差不多是(10^{14})这个级别,用longlong应该就够了

    (m(i))可以欧拉筛预处理一下搞搞,2的幂也可以预处理一下
    复杂度(O(N + T cdot sqrt{N}))

    代码…………
    还没写……鸽王天天鸽

    ---update in 21.5.7---
    代码来了!

    #include<bits/stdc++.h>
    using namespace std;
    #define R register int 
    #define LL long long 
    #define AC 14000000
    #define ac 20000000 + 3
    
    int T, tot;
    LL c, d, x, ans;
    int pri[AC], m[ac];
    bool z[ac];
    LL two[80];
    
    inline int read()
    {
    	int x = 0; char c = getchar(); bool z = 0;
    	while((c > '9' || c < '0') && c != '-') c = getchar();
    	if(c == '-') z = 1, c = getchar();
    	while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
    	return z ? -x : x; 
    }
    
    void get_prime()
    {
    	z[1] = 1;
    	for(R i = 2; i <= 20000000; i ++)
    	{
    		if(!z[i]) pri[++ tot] = i, m[i] = 1;//不要忽略i本身是质数时m(i) = 1
    		for(R j = 1; j <= tot && i * pri[j] <= 20000000; j ++)
    		{
    			z[i * pri[j]] = 1, m[i * pri[j]] = m[i] + 1;
    			if(!(i % pri[j])) 
    			{
    				m[i * pri[j]] --;//如果i * pri[j]剩下那个因子i里也有pri[j]这个因子,那就不用重复统计了
    				break;
    			}
    		}
    	}
    //	printf("%d", tot);
    }
    
    void get_two()//才几十不用快速幂
    {
    	two[0] = 1;
    	for(R i = 1; i <= 63; i ++) two[i] = two[i - 1] << 1;
    }
    
    void work()
    {
    	T = read();
    	while(T --)
    	{
    		c = read(), d = read(), x = read();
    		int t = sqrt(x), now;
    		ans = 0;
    		for(R i = 1; i <= t; i ++)
    		{
    			if(x % i) continue;//首先要是x的因子
    			if(!((i + d) % c))// continue; 这里不能直接continue,因为后面那个可能是可以算的阿
    			{
    				now = (i + d) / c;
    				ans += two[m[now]];//注意now的范围可以很大
    			}
    			if((x / i + d) % c || i * i == x) continue;
    			now = (x / i + d) / c;
    			ans += two[m[now]];
    		}
    		printf("%lld
    ", ans);
    	}
    }
    
    int main()
    {
    	freopen("in.in", "r", stdin);
    	get_prime();
    	get_two();//预处理2的阶乘
    	work();
    	return 0;
    }
    
    本文不允许商业性使用,个人转载请注明出处! 知识共享许可协议
    本作品采用知识共享署名-非商业性使用-禁止演绎 3.0 未本地化版本许可协议进行许可。
  • 相关阅读:
    springboot整合mybatis增删改查(一):项目创建
    springboot结合开源editor.md集成markdonw编辑器
    springboot发送邮件
    史上最全web.xml配置文件元素详解
    一套简约漂亮的响应式博客园主题皮肤分享给你们(二)
    一套简约漂亮的响应式博客园主题皮肤分享给你们(一)
    IDEA中项目统一编码格式设置
    windows上安装Gradle并配置环境变量
    linux自学(九)之开始centos学习,安装数据库MariaDB
    linux自学(七)之开始ccentos学习,安装jdk
  • 原文地址:https://www.cnblogs.com/ww3113306/p/14728004.html
Copyright © 2011-2022 走看看