正睿OI补题(数学基础)

数学基础:

目录:

P1226 【模板】快速幂||取余运算

P1595 信封问题

P3383 【模板】线性筛素数

P3811 【模板】乘法逆元

P1226 【模板】快速幂||取余运算

【模板】快速幂||取余运算 - 洛谷

生日这天又写了一次!!

祝自己生日快乐!!

#include<iostream>
using namespace std;
#define ll long long
ll b,p,k,ans = 1;
int main()
{
	cin>>b>>p>>k;
	
	cout<<b<<"^"<<p<<" mod "<<k<<"=";
	while(p > 0)
	{
		if(p & 1) ans = ans* b % k;
		b = b * b % k;
		p>>=1;//将B的二进制向右移 
	}
	cout<<ans % k<<" "; 
	return 0;
}

P1595 信封问题

P1595 信封问题 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

思路:直接套公式,山东老师告诉我的这个结论 

//错排问题P1595
#include<bits/stdc++.h>
using namespace std;
#define ll long long 
const int N = 25;
ll f[N];
int main()
{
    int n;
    cin>>n;
    f[0] = 1;
    f[1] = 0;
    for(int i = 2;i <= n;i++)
    f[i] = (i-1) * (f[i-1] + f[i-2]);//循环过程中只有一次运算,所以这里不要加括号,会WA
    //以及这里是公式,记住就行,很好记的
    cout<<f[n]<<" ";

    return 0;
}

P3383 【模板】线性筛素数

【模板】线性筛素数 - 洛谷

思路:常见的不就那两个筛,一个是埃氏筛,另外一个是欧拉筛

这题果断欧拉,数据范围在1e8,埃氏筛时间复杂度:O(nloglogn);而欧拉是O(n) 

#include<bits/stdc++.h>
using namespace std;
const int N = 1e8+10; 
int Prime[N];//用来存数组的
bool is_prime[N];
int n,q; 
void oulashai(int n)
{
	int cnt = 0;
	memset(is_prime,true,sizeof(is_prime));
	is_prime[0] = is_prime[1] = 0;
	for(int i = 2;i <= n;i++)
	{
		if(is_prime[i]) Prime[++cnt] = i;
		for(int j = 1;(j <= cnt) && (i*Prime[j]) <=n;j++)//欧拉筛必须从1开始 
		{
			is_prime[i * Prime[j]] = 0;
			if(i % Prime[j] == 0) break;
		 } 
	} 
	return;
}
int main()
{
	cin>>n>>q;
	oulashai(n);
	while(q--)
	{
		int k;
		cin>>k;
		cout<<Prime[k]<<endl;
	}
	
	return 0;
}

埃氏我也补充一下:

#include<bits/stdc++.h>
using namespace std;
int n,q;
const int N = 1e8+10;
bool is_prime[N];
int a[N];
//埃氏筛
void anshishai(int n)
{
	int cnt = 0;
	for(int i = 0;i <= n;i++)is_prime[i] = true;
	is_prime[0] = is_prime[1] = 0;
	for(int i = 1;i <= n;i++)
	{
		if(is_prime[i])
		{
			a[++cnt] = i;
			if(i * i > n)continue;
			for(int j = 2 * i;j <= n;j+=i)is_prime[j] = false;
		}
	}
} 
int main()
{
	cin>>n>>q;
	anshishai(n);
	while(q--)
	{
		int k;
		cin>>k;
		cout<<a[k]<<endl;
	}
	return 0;
 } 

 P3811 【模板】乘法逆元

【模板】乘法逆元 - 洛谷 

思路:直接递推公式即可 

#include<iostream>
using namespace std;
#define ll long long
//扩展欧几里得求逆元
//void exgcd(int a,int b,int &x,int &y)
//{
//   if(b == 0)
//   {
//      x = 1,y = 0;
//  }
//   int gcd = exgcd(b,a % b,y,x);
//   y -= (a/b) * x;
//}
//int _inv(int a,int b)
//{
 //   int x = 1,y = 0;
 //   exgcd(a,p,x,y);
 //   return (x % p + p) % p;
//}
const int N = 3e6+10;
ll n,p;
ll inv[N];
int main()
{
    scanf("%lld%lld",&n,&p);
    inv[1] = 1;
    printf("%lld\n",inv[1]);
    for(int i = 2;i <= n;i++)
    {
        inv[i] = (ll)(-(p/i) * inv[p % i]);
        inv[i] = (ll)(inv[i] % p + p) % p;
        printf("%lld\n",inv[i]);

    }
    
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值