首页 > 其他分享 >p1587-solution

p1587-solution

时间:2024-03-01 09:11:38浏览次数:42  
标签:lfloor right frac gcd sum solution p1587 left

P1587 Solution

link

给你 \(n,m,k\),求满足 \(1\le x\le n,1\le y\le m\) 且最简分数 \(\dfrac x y\) 是 \(k\) 进制下纯循环小数的二元组 \((x,y)\) 个数。

考虑纯循环小数的性质:我们知道纯循环小数的小数部分去除一个循环节后与原数的循环节相等,也就是

\[\frac x y-\left\lfloor\frac x y\right\rfloor=\frac{xk^l}y-\left\lfloor\frac{xk^l}y\right\rfloor \]

其中 \(l\) 表示循环节长度,乘上 \(k^l\) 即将原数左移 \(l\) 位。那么

\[x-y\left\lfloor\frac x y\right\rfloor=xk^l-y\left\lfloor\frac{xk^l}y\right\rfloor \]

\[x\equiv xk^l\pmod y \]

因为 \(\dfrac x y\) 是最简分数,所以 \(\gcd(x,y)=1\),所以

\[k^l\equiv 1\pmod y \]

也就是 \(\gcd(k,y)=1\)。

于是要求的转化为

\[\sum_{i=1}^n\sum_{j=1}^m[\gcd(i,j)=1][\gcd(j,k)=1] \]

下面默认 \(n\le m\)。

\(\begin{aligned} \sum_{i=1}^n\sum_{j=1}^m[\gcd(i,j)=1][\gcd(j,k)=1] &=\sum_{i=1}^n\sum_{j=1}^m\sum_{d|i}\sum_{d|j}\mu(d)[\gcd(j,k)=1]\\ &=\sum_{d=1}^n\mu(d)\sum_{i=1}^{\lfloor\frac n d\rfloor}\sum_{j=1}^{\lfloor\frac m d\rfloor}[\gcd(jd,k)=1]\\ &=\sum_{d=1}^n\mu(d)[\gcd(d,k)=1]\left\lfloor\frac n d\right\rfloor\sum_{j=1}^{\lfloor\frac m d\rfloor}[\gcd(j,k)=1]\\ \end{aligned}\)

设 \(\displaystyle f(n)=\sum_{i=1}^n[\gcd(i,k)=1]\),由于有 \(\gcd(i+k,k)=\gcd(i,k)\),我们可以把 \(f(n)\) 拆成若干长为 \(k\) 的段和最后剩下的一小段,也就是说

\[f(n)=\left\lfloor\frac n k\right\rfloor f(k)+f(n\bmod k) \]

预处理 \(1\sim k\) 的 \(f\) 即可 \(\mathcal O(1)\) 得到 \(f\)。那么

\[\sum_{i=1}^n\sum_{j=1}^m[\gcd(i,j)=1][\gcd(j,k)=1] =\sum_{d=1}^n\mu(d)[\gcd(d,k)=1]\left\lfloor\frac n d\right\rfloor f\left(\left\lfloor\frac m d\right\rfloor\right)\]

现在只需要求出 \(\displaystyle\sum_{d=1}^n\mu(d)[\gcd(d,k)=1]\) 即可整除分块。设 \(\displaystyle g(n)=\sum_{d=1}^n\mu(d)[\gcd(d,k)=1]\),于是

\[g(n)=\sum_{i=1}^n[\gcd(i,k)=1]g\left(\left\lfloor\frac n i\right\rfloor\right)-\sum_{i=2}^n[\gcd(i,k)=1]g\left(\left\lfloor\frac n i\right\rfloor\right) \]

考虑前半部分

\(\begin{aligned} \sum_{i=1}^n[\gcd(i,k)=1]g\left(\left\lfloor\frac n i\right\rfloor\right) &=\sum_{i=1}^n[\gcd(i,k)=1]\sum_{j=1}^{\lfloor\frac n i\rfloor}\mu(j)[\gcd(j,k)=1]\\ &=\sum_{i=1}^n\sum_{j=1}^{\lfloor\frac n i\rfloor}\mu(j)[\gcd(ij,k)=1]\\ \end{aligned}\)

令 \(s=ij\)

\(\begin{aligned} \sum_{i=1}^n[\gcd(i,k)=1]g\left(\left\lfloor\frac n i\right\rfloor\right) &=\sum_{s=1}^n[\gcd(s,k)=1]\sum_{j|s}\mu(j)\\ &=\sum_{s=1}^n[\gcd(s,k)=1][s=1]\\ &=1 \end{aligned}\)

所以 \(\displaystyle g(n)=1-\sum_{i=2}^n[\gcd(i,k)=1]g\left(\left\lfloor\frac n i\right\rfloor\right)\)

这里 \([\gcd(i,k)=1]\) 的前缀和就是 \(f\),所以整除分块递推计算即可。

复杂度大概是 \(\displaystyle\mathcal O(n^{\frac 3 4}+k)\) 的,预处理一部分的 \(g\) 可以做到 \(\displaystyle\mathcal O(n^{\frac 2 3}+k)\)。

代码

using namespace std;
const int N = 1e6 + 10;
const int inf = ~0u >> 2;
bool ip[N];
int mu[N],prime[N],cnt;
int f[N],g[N];
void sieve(int n)
{
	cnt = 0;
    memset( ip , true , sizeof(ip) );
    ip[0] = ip[1] = false,mu[1] = 1;
	for(int i = 2;i <= n;i++)
    {
        if( ip[i] )
            prime[++cnt] = i,mu[i] = -1;
        for(int j = 1;j <= cnt && i * prime[j] <= n;j++)
        {
            ip[ i * prime[j] ] = false;
            if(i % prime[j] == 0)
            	break;
        	mu[ i * prime[j] ] = -mu[i];
        }   
    }
}
int n,m,k;
int sum_f(int n)
	{return f[k] * (n / k) + f[n % k];}
unordered_map<int , int> mp;
int sum_g(int n)
{
	if(n <= N - 10)
		return g[n];
	if( mp.find(n) != mp.end() )
		return mp[n];
	int l = 2,r,res = 1;
	while(l <= n)
	{
		r = n / (n / l);
		res -= ( sum_f(r) - sum_f(l - 1) ) * sum_g(n / l);
		l = r + 1;
	}
	return mp[n] = res;
}
LL h(int n , int m)
{
	int l = 1,r;
	LL res = 0;
	while( l <= min(n , m) )
	{
		r = min( n / (n / l) , m / (m / l) );
		res += 1ll * ( sum_g(r) - sum_g(l - 1) ) * (n / l) * sum_f(m / l);
		l = r + 1;
	}
	return res;
}
int main()
{
	sieve(N - 10);
	cin >> n >> m >> k;
	for(int i = 1;i <= k;i++)
		f[i] = f[i - 1] + (__gcd(i , k) == 1);
	for(int i = 1;i <= N - 10;i++)
		g[i] = g[i - 1] + mu[i] * ( sum_f(i) - sum_f(i - 1) );
	cout << h(n , m) << endl;
    return 0;
}

标签:lfloor,right,frac,gcd,sum,solution,p1587,left
From: https://www.cnblogs.com/iorit/p/18046091

相关文章

  • 2.29闲话 & solution 『任无数/花开花落之后/你仍君临芸芸众生』
    明天就省选了,我咋啥也不会最破防的一集一道LCT调了一下午没调出来最后发现是min和max取反了改完之后发现自己的访问有问题,如果有0边权我就会直接返回LLONG_MAX啊哈哈,我调了一下午,发了7个帖子然后校内OJ过了,POJ因为只有C++98所以CE了哈哈哈写个简要题解吧[......
  • P10202 [湖北省选模拟 2024] 沉玉谷 Solution
    好像比题解劣一个\(n\),但是也跑的很快。首先说明,问题等价于计算有多少种本质不同的方案使得整个序列被删完,证明省略。考虑用区间的方式表述这些操作,具体的,忽略删除后的移位操作,将每次删除的左右段点视为一个区间,则一定会有:区间的并是\([1,n]\)。区间之间要么不交,要么包含。......
  • solution-P1667(more)
    这道题,我不会做,我就是菜,我就是没水平,我就是傻逼。这道题,我不会做,我就是菜,我就是没水平,我就是傻逼。这道题,我不会做,我就是菜,我就是没水平,我就是傻逼。正文直接前缀和,发现操作相当交换\(s_{i-1},s_j\),显然最后我们只需要让\(s\)单调上升即可。直接做,找有多少个环,答案为\(n......
  • niu-zi-solution
    牛子Solutionlink结论:一个方案合法当且仅当,每行数种类为\(2\),或者每列数种类为\(2\)。证明:我们试图证明,如果一个方案存在一行的数种类\(\ge3\),则这个方案的每列数种类为\(2\)。对于有\(\ge3\)种数的这一行,必然存在某连续的三个数两两不同,即形如abc的形式。这个可以......
  • cf1748f-solution
    CF1748FSolutionlink题目也就是要我们交换每对\(a_i\)和\(a_{n-1-i}\)。考虑如何利用这个异或操作交换:我们自然地想到x^=y,y^=x,x^=y。如何操作使得x^=y?我们把环上\(x\)到\(y\)的路径拉出来,假装是个序列:\(a_x.a_{x+1},a_{x+2},\dots,a_{y-2},a_{y-1},a_y\)现在要使......
  • cf1621g-solution
    CF1621GSolutionlink考虑对每个位置\(i\)作为\(i_j\)时计算贡献。\(i\)对一次答案有贡献当且仅当:设其子序列内最右端的位置为\(r\),则要满足\(r\)右侧存在一个数大于\(a_{i}\)。即,设\(lst_i\)表示整个序列最右侧的大于\(a_i\)的数,要满足\(lst_i>r\)。现......
  • cf1606e-solution
    CF1606ESolutionlink考虑dp。注意到这个题造成的伤害与剩余人数有关,每次消灭的人数又与剩余人的血量最大值有关:设\(dp_{i,j}\)表示剩下\(i\)个人中血量最大值为\(j\)的方案数。显然当\(i-1>=j\)时一次伤害就可以杀光所有人,于是这时\(dp_{i,j}=j^i-(j-1)^i\)(只需让......
  • cf1599j-solution
    CF1599JSolutionlink题意:给你一个长为\(n\)的序列\(b\),请你构造一个长为\(n\)的序列\(a\),满足\(b\)中的数都能由\(a\)中两个不同下标的数相加得到。无解报告NO,\(n\le10^3,b_i\le10^6\)。我们发现如果我们能用\(a_1\sima_m\)来凑出\(b_1\simb_m\),剩下的令......
  • cf1583h-solution
    CF1583HSolutionlink第一问容易处理,将边权从大到小排序,并查集维护一下连通块最大值简单搞搞就好。考虑第二问。我们对原树,按照\(t\)的权值建造克鲁斯卡尔重构树,那么两点的lca权值即它们路径上边权最大值。同样按照边权\(c\)从大到小将边排序,维护连通块内最大值的同时,维......
  • cf1555f-solution
    CF1555FSolutionlink分析一张图中的环,我们可以考虑把图表示为一棵生成树加上许多非树边。对于这题,我们考虑动态维护一片森林,在每次准备加一条边\((u,v)\)时:如果这条边加进去后与森林不形成环,那么它与图肯定也不形成环,那么直接加进森林中。如果这条边是森林的一条非树......