Math is Simple[杭电2020第一场][数学变形][数论变换]

文章目录

题目

HDU
在这里插入图片描述

2 n 1 0 8 2\le n\le 10^8

思路

考试时候一直在想什么杜教筛和分块,但是数组开不下而且好像错了
这个分数裂项简直绝了
考虑记
f n = 1 a < b n g c d ( a , b ) = 1 a + b n 1 a b f_n=\sum_{\begin{matrix}1\le a<b\le n\\gcd(a,b)=1\\a+b\ge n\end{matrix}}\frac{1}{ab}
考虑递推,那么新增的必定有 b = n b=n 而且还要减去 a + b = n 1 a+b=n-1 的方案
f n = f n 1 + 1 a n g c d ( a , n ) = 1 1 a n 1 a < b n 1 g c d ( a , b ) = 1 a + b = n 1 1 a b f_n=f_{n-1}+\sum_{\begin{matrix}1\le a\le n\\gcd(a,n)=1\end{matrix}}\frac{1}{an}-\sum_{\begin{matrix}1\le a<b\le n-1\\gcd(a,b)=1\\a+b=n-1\end{matrix}}\frac{1}{ab}
然后开始操作了…
发现减去的似乎有点搞头,记 g n = 1 a < b n g c d ( a , b ) = 1 a + b = n 1 a b g_n=\sum_{\begin{matrix}1\le a<b\le n\\gcd(a,b)=1\\a+b= n\end{matrix}}\frac{1}{ab}
有边界 g 2 = 0 g_2=0
然后因为 g c d ( a , b ) = g c d ( a , a + b ) = g c d ( a , n ) = g c d ( b , n ) , 1 a b = 1 n ( 1 a + 1 b ) gcd(a,b)=gcd(a,a+b)=gcd(a,n)=gcd(b,n),\frac{1}{ab}=\frac{1}{n}(\frac{1}{a}+\frac{1}{b})
于是有
g n = 1 n 1 a < b n g c d ( a , b ) = 1 a + b = n 1 a + 1 b g_n=\frac{1}{n}\sum_{\begin{matrix}1\le a<b\le n\\gcd(a,b)=1\\a+b= n\end{matrix}}\frac{1}{a}+\frac{1}{b}
g n = 1 n 1 a n g c d ( a , n ) = 1 1 a g_n=\frac{1}{n}\sum_{\begin{matrix}1\le a\le n\\gcd(a,n)=1\end{matrix}}\frac{1}{a}
惊奇的发现和 f n f_n 的表达式扯上关系
于是
f n = f n 1 + g n g n 1 f_n=f_{n-1}+g_n-g_{n-1}
这真的很离谱,
然后 f n 1 = f n 2 + g n 1 g n 2 f_{n-1}=f_{n-2}+g_{n-1}-g_{n-2}
代入,一直到
f n = f 2 g 2 + g n = 1 2 + g n f_n=f_2-g_2+g_n=\frac{1}{2}+g_n
然后只用求 g n g_n
接着莫比乌斯反演
g n = 1 n i = 1 n 1 i [ g c d ( i , n ) = 1 ] = 1 n i = 1 n 1 i d ( i , n ) μ d = 1 n d n μ d 1 d i = 1 n d 1 i = 1 n d n μ ( d ) 1 d S ( n d ) g_n=\frac{1}{n}\sum_{i=1}^n\frac{1}{i}[gcd(i,n)=1]=\frac{1}{n}\sum_{i=1}^n\frac{1}{i}\sum_{d|(i,n)}\mu_d\\=\frac{1}{n}\sum_{d|n}\mu_d\frac{1}{d}\sum_{i=1}^{\lfloor\frac{n}{d}\rfloor}\frac{1}{i}=\frac{1}{n}\sum_{d|n}\mu(d)\frac{1}{d}S(\lfloor\frac{n}{d}\rfloor)
然后就可以 O ( n ) O(n) 算出 S ( n ) S(n)
然后由于空间限制 512 M b 512Mb ,一个 1 e 8 1e8 的数组是 350 M b 350Mb 左右,你不能 O ( n ) O(n) 筛出 μ \mu ,要将 n n 质因数分解后类似二进制枚举搞出 g n g_n

代码

#include<set>
#include<map>
#include<stack>
#include<queue>
#include<deque>
#include<cmath>
#include<ctime>
#include<cstdio>
#include<vector>
#include<climits>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define LL long long
LL read(){
    LL f=1,x=0;char c=getchar();
    while(c<'0'||'9'<c){if(c=='-')f=-1;c=getchar();}
    while('0'<=c&&c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
    return f*x;
}
#define INF 0x3f3f3f3f
#define Mod 998244353
#define MAXN 100000000
inline int Sub(register int x,register int y){x-=y;return x<0?x+Mod:x;}
inline int Add(register int x,register int y){x+=y;return x>=Mod?x-Mod:x;}
inline int Mul(register LL x,register int y){x*=y;return x>=Mod?x%Mod:x;}
int Pow(int x,LL y){
	int ret=1;
	while(y){
		if(y&1) ret=Mul(ret,x);
		x=Mul(x,x);
		y>>=1;
	}
	return ret;
}
int n,inv[MAXN+5],cnt,p[30],ans;
void DFS(int x,int d,int u){
	if(x>cnt){
		ans=Add(ans,Mul(Mul(u,Sub(inv[d],inv[d-1])),inv[n/d]));
		return ;
	}
	DFS(x+1,d,u);
	DFS(x+1,d*p[x],Mod-u);
	return ;
}
int main(){
	inv[1]=1;
	for(int i=2;i<=MAXN;i++)
		inv[i]=(Mod-(1ll*Mod/i*inv[Mod%i]%Mod))%Mod;
	for(int i=2;i<=MAXN;i++)
		inv[i]=Add(inv[i],inv[i-1]);
	int T=read();
	while(T--){
		ans=0,cnt=0,n=read();
		int tmp=n;
		for(int i=2;i*i<=tmp;i++)
			if(tmp%i==0){
				p[++cnt]=i;
				while(tmp%i==0)
					tmp/=i;
			}
		if(tmp>1)
			p[++cnt]=tmp;
		if(n!=2)
			DFS(1,1,1);
		else ans=0;
		ans=Mul(ans,Sub(inv[n],inv[n-1]));
		printf("%d\n",Add(ans,inv[2]-1));
	}
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_37555704/article/details/107499528