2021 GDUT 新生专题训练 数论

4 篇文章 0 订阅
4 篇文章 0 订阅

数论

知识总结

快速幂

long long binpow(long long a, long long b, long long m) {
  a %= m;
  long long res = 1;
  while (b > 0) {
    if (b & 1) res = res * a % m;
    a = a * a % m;
    b >>= 1;
  }
  return res;
}

素数判定

暴力做法
米勒罗宾判定
  • 费马小定理
  • 二次探测定理

bool millerRabbin(int n) {
  if (n < 3) return n == 2;
  int a = n - 1, b = 0;
  while (a % 2 == 0) a /= 2, ++b;
  // test_time 为测试次数,建议设为不小于 8
  // 的整数以保证正确率,但也不宜过大,否则会影响效率
  for (int i = 1, j; i <= test_time; ++i) {
    int x = rand() % (n - 2) + 2, v = quickPow(x, a, n);
    if (v == 1 || v == n - 1) continue;
    for (j = 0; j < b; ++j) {
      v = (long long)v * v % n;
      if (v == n - 1) break;
    }
    if (j >= b) return 0;
  }
  return 1;
}

最大公约数

int gcd(int a, int b) {
  return b == 0 ? a : gcd(b, a % b);
}

拓展欧几里得

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

素数筛法

欧拉筛法
const int maxn = 50005;
int prime[maxn] , visit[maxn] , vis[1000005];
void Prime(){
    memset (prime, 0 , sizeof (prime));
    memset (visit, 1 , sizeof (visit));
	visit[1] = 0;
	
	for(int i = 2; i <= maxn; i++) {
		if(visit[i])
			prime[++prime[0]] = i;
			
		for(int j = 1; j <= prime[0] && i*prime[j] <= maxn; j++) {
			visit[i*prime[j]] = 0;
            
			if(i % prime[j] == 0) { 
				break; 
			}
		}
	}
}

乘法逆元

费马小定理

逆元x为a^(b-2) mod b a是元,b是模数

int ksm(long long a, int b) {
  int ans = 1;
  a = (a % p + p) % p;
  for (; b; b >>= 1) {
    if (b & 1) ans = (a * ans) % p;
    a = (a * a) % p;
  }
  return ans;
}

线性同余方程

int exgcd(int a, int b, int& x, int& y) {
  if (b == 0) {
    x = 1, y = 0;
    return a;
  }
  int g = exgcd(b, a % b, y, x);
  y -= a / b * x;
  return g;
}
bool liEu(int a, int b, int c, int& x, int& y) {
  int d =  exgcd(a, b, x, y);
  if (c % d != 0) return 0;
  int k = c / d;
  x *= k;
  y *= k;
  return 1;
}

质因数分解

list<int> breakdown (int N) {
  list<int> result;
  for (int i = 2; i * i <= N; i++) {
    if (N % i == 0) {
      while (N % i == 0) N /= i;
      result.push_back(i);
    }
  }
  if (N != 1)
    result.push_back(N)
  return result;
}

题解

题目

A - k-rounding

For a given positive integer n denote its k-rounding as the minimum positive integer x, such that x ends with k or more zeros in base 10 and is divisible by n.

For example, 4-rounding of 375 is 375·80 = 30000. 30000 is the minimum integer such that it ends with 4 or more zeros and is divisible by 375.

Write a program that will perform the k-rounding of n.

input

The only line contains two integers n and k (1 ≤ n ≤ 1e9, 0 ≤ k ≤ 8).

output

Print the k-rounding of n.

样例
input
375 4
output
30000
input
10000 1
output
10000
input
38101 0
output
38101
input
123456789 8
output
12345678900000000
思路
求n的倍数中有k个零的最小数
即lcm(n,10^k)
故直接快速幂与最大公约数即可求得
代码
#include <iostream>
using namespace std;
typedef long long ll;
ll gcd (ll a , ll b) {
	return a % b ? gcd (b , a % b) : b;
} 
ll ksm (ll a , ll b) {
	ll res = 1;
	while (b > 0) {
		if (b & 1) res = res * a;
		a = a * a;
		b >>= 1;
	}
	return res;
}
int main () {
	ll n , k , p;
	cin >> n >> k;
	p = ksm (10 , k);
	cout << n * p / gcd (n , p);
	return 0;
}

题目

B - Fedya and Maths

Fedya studies in a gymnasium. Fedya’s maths hometask is to calculate the following expression:

(1^n + 2^n + 3^n + 4^n) mod 5

for given value of n. Fedya managed to complete the task. Can you? Note that given number n can be extremely large (e.g. it can exceed any integer type of your programming language).

input

The single line contains a single integer n (0 ≤ n ≤ 10105). The number doesn’t contain any leading zeroes.

output

Print the k-rounding of n.

样例
input
4
output
4
input
124356983594583453458888889
output
0
思路
打表找规律后可知每4个一个循环 若是4的倍数则是4 否则为0
代码
#include <iostream>
#include <cstring>
using namespace std;
typedef long long ll;
int main () {
	string a;
	cin >> a;
	ll len = a.length() , num;
	if (len >= 2) {
		num = (a[len-2]-'0') * 10 + (a[len-1]-'0');
	} else {
		num = a[len-1]-'0';
	}
	if (num % 4) cout << 0;
	else cout << 4;
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值