11.30数学集合

题目来源:能力提升综合题单Part6 数学1

\(Exgcd\)

求解形如下的不定方程

\[ax+by = c \]

关于该方程的性质
\(1°\)首先若方程有解则,\(gcd(a,b)\mid c\),否则无解
\(2°\)求得一组特解\(x^ {'},y^{'}\),那么其通解形如

\[x=x^{'}+\frac{b}{gcd(a,b)}t,t∈Z \]

\[y=y^{'}-\frac{a}{gcd(a,b)}t,t∈Z \]

\(3°\)
\(x\)最小值为\(x^{'} \mod \frac{b}{gcd(a,b)}\)
\(y\)最小值为\(y^{'}\mod\frac{a}{gcd(a,b)}\)

注意在实际中\(Exgcd\)并不能处理\(a,b\)为负数的情况
常用手段是按题意取相反数

青蛙的约会

推一波式子就会发现
问题转化为求解

\[lp+(n-m)q = x-y \]

\(q\)的最小正整数解

直接套用\(Exgcd\)就基本可以解决问题了

有一个小细节需要注意一下
\(l\)\(n-m\)为负数时,需要将\(n-m\)\(x-y\)取一下相反数来解决问题

Code

#include<iostream>
#include<cstdio>

using namespace std;

#define int long long 

template<typename _T>
void read(_T &x)
{
	x=0;char s=getchar();int f=1;
	while('0'>s||s>'9'){f=1;if(s=='-')f=-1;s=getchar();}
	while('0'<=s&&s<='9'){x=(x<<3)+(x<<1)+s-'0';s=getchar();}
	x*=f;
}

inline int gcd(int a,int b)
{
	if(b==0) return a;
	else return gcd(b,a%b);
}

inline void Exgcd(int a,int b,int &x,int &y)
{
	if(b==0)
	{
		x=1ll;y= 0;
		return;
	}
	Exgcd(b,a%b,x,y);
	int t = x;
	x=y;
	y=t-(a/b)*y; 
}

signed main()
{
	int x,y,m,n,l;
	
	ios_base::sync_with_stdio(false);
	cout.tie(NULL);
	cin.tie(NULL);
	
	read(x);
	read(y);
	read(m);
	read(n);
	read(l);
	
	int xx,yy,num;
	
	int a,b,c;
	
	a= l,b=n-m,c=(x-y);
	if(b < 0)
	{
		c=-c;
		b=-b;
	}
	num = gcd(a,b);
	
	if(c%num != 0) 
	{
		cout<<"Impossible";
		return 0;
	}
	
	Exgcd(b,a,xx,yy);
	
	xx*=c/num;
	yy*=c/num;
	
	cout<<((xx)%(a/num)+(a/num))%(a/num);
}

欧拉函数\(\phi\)

欧拉函数线筛

先来一发线筛

inline void prime_phi(int n)
{
	phi[1] =1;
	for(int i=2;i<=n;i++)
	{
		if(!vis[i]) 
		{
			prime[++st] = i;
			phi[i] = i-1;
			vis[i] = i;
		}
		for(int j=1;j<=st;j++)
		{
			if(prime[j] > vis[i] || i*prime[j] > n) break;
			vis[i*prime[j]] = prime[j];
			if(i%prime[j]==0)
			phi[i*prime[j]] = phi[i] * prime[j];
			else phi[i*prime[j]] = phi[i]*(prime[j]-1);
		}
	}
}

线筛写错了就等着崩盘吧

欧拉函数性质

欧拉函数多用于求解与互质相关的题目

若在\(N\)的算术基本定理中\(N=p_{1}^{c_1} p_{2}^{c_2}…p_{m}^{c_m}\)

那么有

\[\phi(N) =N\times \frac{p_1-1}{p_1}\times\frac{p_2-2}{p_2}\times… \times\frac{p_m-1}{p_m} \]

\(1.\)\(a,b\)互质,则\(\phi(ab)=\phi(a)\phi(b)\)
该性质说明了欧拉函数为积性函数

\(2.\)\(p\)为素数若\(p\mid n\)\(p^2\mid n\),则\(phi(n)=phi(\frac{n}{p})\times p\)
\(3.\)\(p\)为素数若\(p\mid n\)\(p^2\nmid n\),则\(phi(n)=phi(\frac{n}{p})\times (p-1)\)
\(4.\) \(\sum_{d\mid n}\phi(i)=n\)

GCD SUM

原式要求

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

考虑对每一个\(gcd(i,j)\)
假如其不为\(1\)
设为\(gcd(i,j)=p\)
其贡献可以转化为\(gcd(\frac{i}{p},\frac{j}{p})\times p\)
所以问题就被转化为了对一个数\(\frac{i}{p}求phi(\frac{i}{p})\times p\)
这样\(gcd(i,j)=p\)的贡献就可以在\(\frac{i}{p},\frac{j}{p}\)时被算出来

那么原式可以化为

\[\sum_{i=1}^{n}\sum_{p=1}^\frac{n}{i}\phi(i)\times p \]

\[\sum_{p=1}^\frac{n}{i}\phi(i) \]

这个东西显然可以前缀和求解

有些小细节需要注意:
算出来的结果需要再乘2,然后容斥一下就好了

Code

#include<iostream>
#include<cstdio>
#include<vector>
#include<cmath>

using namespace std;

#define int long long 
const int p=1e6+5;


template<typename _T>
void read(_T &x)
{
	x=0;char s=getchar();int f=1;
	while('0'>s||s>'9'){f=1;if(s=='-')f=-1;s=getchar();}
	while('0'<=s&&s<='9'){x=(x<<3)+(x<<1)+s-'0';s=getchar();}
	x*=f;
}

inline int gcd(int a,int b)
{
	if(b==0) return a;
	else return gcd(b,a%b);
}

int vis[p];
int prime[p];
int phi[p];
int st;
int n;

inline void prime_phi(int n)
{
	phi[1] =1;
	for(int i=2;i<=n;i++)
	{
		if(!vis[i]) 
		{
			prime[++st] = i;
			phi[i] = i-1;
			vis[i] = i;
		}
		for(int j=1;j<=st;j++)
		{
			if(prime[j] > vis[i] || i*prime[j] > n) break;
			vis[i*prime[j]] = prime[j];
			if(i%prime[j]==0)
			phi[i*prime[j]] = phi[i] * prime[j];
			else phi[i*prime[j]] = phi[i]*(prime[j]-1);
		}
	}
}

signed main()
{
	ios_base::sync_with_stdio(false);
	cout.tie(NULL);
	cin.tie(NULL);
	
	read(n);
	
	prime_phi(n);
	
	int sum = 0;
	
	for(int i=1;i<=n;i++)
		for(int p=1;p<=n/i;p++)
		{
			sum+=phi[i]*p;
		}
	
	sum*=2;
	
	for(int i=1;i<=n;i++)
	{
		sum-=i;
	}
	
	cout<<sum;
}

附:扩展欧拉定理

\[a^b ≡ \begin{cases} a^{b\mod \phi(p)} & \text{gcd(a,p)=1)}\\ a^{b\mod \phi(p)+\phi(p)} & \text{$gcd(a,p)≠1$,b>$\phi$(p)}\\ a^b & \text{$gcd(a,p)≠1$,b≤$\phi$(p) } \end{cases} \]

\(End\)

posted @ 2020-11-30 21:46  ·Iris  阅读(206)  评论(0编辑  收藏  举报