数论----持续更新

1.约束和定理

数论----持续更新_第1张图片

 

2.逆元

求逆元的2种模板

(1) exgcd 求逆元

x->a关于b的逆元

y->b关于a的逆元

typedef long long LL

void ex_gcd(LL a, LL b, LL &x, LL &y, LL &d)
{

      if (!b) {d = a, x = 1, y = 0;}

      else
     {

          ex_gcd(b, a % b, y, x, d);

          y -= x * (a / b);

      }

}

LL inv(LL t, LL p)
{//如果不存在,返回-1 

     LL d, x, y;

     ex_gcd(t, p, x, y, d);

     return d == 1 ? (x % p + p) % p : -1;

 }

(2)快速幂+费马小定理求逆元



// 快速幂求逆元

LL pow_mod(LL a, LL b, LL p)
{//a的b次方求余p 

     LL ret = 1;

     while(b){

         if(b & 1) ret = (ret * a) % p;

         a = (a * a) % p;

         b >>= 1;

     }

     return ret;

 }

LL Fermat(LL a, LL p)
{//费马求a关于b的逆元 

         return pow_mod(a, p-2, p);

 }

3.莫比乌斯反演

 (1)  整除分块

可以用到整除分块的形式,大致是这样的:          \sum_{i=1}^{n}\left \lfloor \frac{n}{i} \right \rfloor

打表:

数论----持续更新_第2张图片数论----持续更新_第3张图片

对于每一个  \left \lfloor\frac{n}{i} \right\rfloor  我们可以通过打表(或理性的证明)可以发现:

有许多的值是一样的,而且它们呈一个块状分布;再通过打表之类的各种方法,我们惊喜的发现对于每一个值相同的块,它的最后一个数就是   \frac{n}{\left \lfloor \frac{n}{i} \right \rfloor}。得出这个结论后,我们就可以做的O(\sqrt{n})处理了。
附一个整除分块的代码吧:

for(int l=1,r;l<=n;l=r+1)
{
    r=n/(n/l);
    ans+=(r-l+1)*(n/l);//个数*值 
}

(2) 与其他函数的联系

  • 有时候,可能推出来的式子不一定就是一个很裸的整除分块,可能会与某些积性函数相乘,如:μ,,φ...... 这时候,我们就需要对这些函数统计一个前缀和。因为,每当我们使用整除分块跳过一个区间的时候,其所对应的函数值也跳过了一个区间。所以此时,就需要乘上那一个区间的函数值。
  • (当然,如果当出题人想要考考你的数论能力的话,这时就不是统计前缀和这么简单了。可能O(n)线筛都会TLE,那么我们就需要杜教筛了)
  • https://www.cnblogs.com/peng-ym/p/9446555.html   

(3)莫比乌斯反演

 

 

 

 

题目

HDU 1452

大意:求2004^n的约束和

约束和+快速幂+逆元

#include
using namespace std;
// 快速幂
long long pow_mod(long long a, long long b,long long p)
{//a的b次方求余p 
    long long ret = 1;
     while(b)
	 {
         if(b&1)ret=(ret*a)%p;
          a=(a*a)%p;
          b>>=1;

     }
    return ret;
 }
long long Fermat(long long  a, long long  p)
{//费马求a关于b的逆元 
     return pow_mod(a, p-2, p);
}
int main()
{
	int n;
	while(~scanf("%d",&n))
	{
		if(n==0)break;
		long long a,b,c;
		a=pow_mod(2,2*n+1,29)-1;
		b=pow_mod(3,n+1,29)-1;
		c=pow_mod(167,n+1,29)-1;
		long long ans=(a*b*c*9)%29;
		printf("%lld\n",ans);
	}
	//printf("%lld",Fermat(332,29));==9
	return 0;
}

HDU 1695

大意:给出n、m、k ,求出1<=x<=n, 1<=y<=m 且gcd(x,y) == k 的(x,y)的对数

 

 

你可能感兴趣的:(数论----持续更新)