数论

数论这东西,感觉套模板的地方比较多。然后模板又有些类似的地方,想要记忆和区分并使用的话,还是得要对公式的由来进行推导记忆。此处主要对写数论题目时经常会用到的公式的概括。

目录

1.gcd和lcm

2.快速幂

3.欧拉函数

4.拓展欧几里得

5.中国剩余定理

6.总结


1.gcd和lcm

列出来是因为太常用了。但因为太常用,就不列代码了。

2.快速幂

快速幂在只需要得到某些特别大的数对某个数的余数时特别有用。有时也变化为求指数的后几位数。(此处还提一下位运算,虽然说运算快一些,但平时也看不出来快在哪里,但有一些时间限制特别严苛的题目,用了位运算和没用就是TLE和AC的区别)

ll quickpow(ll ai,ll bi,ll m)
{
	ll all = 1;
	while (bi)
	{
		if (bi & 1)
		{
			all = all * ai % m;
		}
		ai = ai * ai % m;
		bi >>= 1;
	}
	return all;

}

 例题:POJ—3358

#include<iostream>
#include<string>
#include<map>
#include<vector>
#include<algorithm>
#include<cmath>

using namespace std;
typedef long long ll;

ll gcd(ll a, ll b)
{
	if (b == 0)
	{
		return a;
	}
	return gcd(b, a % b);
}

ll quickpow(ll a, ll b, ll m)
{
	ll all = 1;
	while (b)
	{
		if (b & 1)
		{
			all = a * all % m;
		}
		a = a * a % m;
		b >>= 1;
	}
	return all;
}

ll exgcd(ll a, ll b, ll& x, ll& y)
{
	if (b == 0)
	{
		x = 1;
		y = 0;
		return a;
	}
	ll ans;
	ans = exgcd(b, a % b, x, y);
	ll r;
	r = x;
	x = y;
	y = r - a / b * y;
	return ans;
}

ll ola(ll a)
{
	ll ans = a;
	for (ll i = 2;i * i <= a;i++)
	{
		if (a % i == 0)
		{
			ans = ans * (i - 1) / i;
			while (a % i == 0)
			{
				a /= i;
			}
		}
	}
	if (a > 1)
	{
		ans = ans * (a - 1) / a;
	}
	return ans;
}
int main()
{
	ll a, b;
	ll s = 1;
	while (cin >> a)
	{
		getchar();
		cin >> b;
		ll gc;
		if (a > b)
			gc = gcd(a, b);
		else
			gc = gcd(b, a);
		a = a / gc;
		b = b / gc;
		ll x=0;
		while(b % 2 == 0)
		{
			b /= 2;
			x++;
		}
		ll num = ola(b);
		ll ans;
		for (ll i = 1;i * i <= num;i++)
		{
			if (num % i == 0)
			{
				if (quickpow(2, i, b) == 1)
				{
					ans = i;
					break;
				}
				else if (quickpow(2, num / i, b) == 1)
				{
					ans = num / i;
				}
			}
		}
		cout <<"Case #"<<s++<<": "<< x+1 << "," << ans << endl;

	}

	return 0;
}

3.欧拉函数

1∼N 中与 N互质的数的个数被称为欧拉函数,记为φ ( N )

ll ola(ll a)
{
	ll ans = a;
	for (ll i = 2;i * i <= a;i++)
	{
		if (a % i == 0)
		{
			ans = ans * (i - 1) / i;
			while (a % i == 0)
			{
				a /= i;
			}
		}
	}
	if (a > 1)
	{
		ans = ans * (a - 1) / a;
	}
	return ans;
}

 性质:

1.欧拉函数是积性函数,若m , n m,nm,n互质,则φ ( m n ) = φ ( n ) φ ( m )
2. 2.2.当n nn为质数时,φ ( n ) = n − 1
3. 3.3.当n nn为奇质数时,φ ( 2 n ) = φ ( n )

解决特定的题目,知道公式就能解决,不知道就凉凉。

4.拓展欧几里得

这个就是经常会用在互质的情况下。

ll exgcd(ll a, ll b, ll& x, ll& y)
{
	if (b == 0)
	{
		x = 1;
		y = 0;
		return a;
	}
	ll ans;
	ans = exgcd(b, a%b, x, y);
	ll r;
	r = x;
	x = y;
	y = r - a / b * y;
	return ans;
}

5.中国剩余定理

更加迷惑了,虽然知道怎么用,但是看来看去还是没搞懂,大概率是马上又忘了。

ll China(int n,ll *m,ll *a)
{
    ll M=1,d,y,x=0;
    for(int i=0;i<n;i++) M*=m[i];
    for(int i=0;i<n;i++){
        ll w=M/m[i];
        gcd(m[i],w,d,d,y);
        x=(x+y*w*a[i])%M;
    }
    return (x+M)%M;
}

也是求逆元,逆元就更加迷糊了。

6.总结

菜还是真的菜,感觉写这些题的时候还是认为理解了,但结果碰到换了问法,就又是从头来过,这确实是不得要领。

对于最后两个,拓展欧几里得和中国剩余定理,这个当时就光一题就是一天,结果写完一题,下一题还是不行,套模板虽然说很有用吧,但就是想不出原理是什么了。这两项一直都伴随这求逆元这个东西,这个对于我就个麻烦了,连总结都不知道该怎么总结。

总的来说,不会的最大原因肯定是时间没花上去,但是怎么分配时间就成了大问题,也有可能是没从放松的心态转变过来吧。这是这次的最后一天。希望下次博客就能够得到一个合理的安排,不至于这样。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值