zoukankan      html  css  js  c++  java
  • 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^{'}modfrac{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 imes frac{p_1-1}{p_1} imesfrac{p_2-2}{p_2} imes… imesfrac{p_m-1}{p_m} ]

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

    (2.)(p)为素数若(pmid n)(p^2mid n),则(phi(n)=phi(frac{n}{p}) imes p)
    (3.)(p)为素数若(pmid n)(p^2 mid n),则(phi(n)=phi(frac{n}{p}) imes (p-1))
    (4.) (sum_{dmid 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}) imes p)
    所以问题就被转化为了对一个数(frac{i}{p}求phi(frac{i}{p}) imes p)
    这样(gcd(i,j)=p)的贡献就可以在(frac{i}{p},frac{j}{p})时被算出来

    那么原式可以化为

    [sum_{i=1}^{n}sum_{p=1}^frac{n}{i}phi(i) imes 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 ≡ egin{cases} a^{bmod phi(p)} & ext{gcd(a,p)=1)}\ a^{bmod phi(p)+phi(p)} & ext{$gcd(a,p)≠1$,b>$phi$(p)}\ a^b & ext{$gcd(a,p)≠1$,b≤$phi$(p) } end{cases} ]

    (End)

  • 相关阅读:
    leetcode 190 Reverse Bits
    vs2010 单文档MFC 通过加载位图文件作为客户区背景
    leetcode 198 House Robber
    记忆化搜索(DP+DFS) URAL 1183 Brackets Sequence
    逆序数2 HDOJ 1394 Minimum Inversion Number
    矩阵连乘积 ZOJ 1276 Optimal Array Multiplication Sequence
    递推DP URAL 1586 Threeprime Numbers
    递推DP URAL 1167 Bicolored Horses
    递推DP URAL 1017 Staircases
    01背包 URAL 1073 Square Country
  • 原文地址:https://www.cnblogs.com/-Iris-/p/14063976.html
Copyright © 2011-2022 走看看