Number theory (modulus, fast power, Euclidean algorithm, extended Euclidean algorithm, prime number sieve) + examples (A/B, frog's date, beautiful prime numbers)

Number Theory

model

Several important formulas about modulus:

1.(ab)%c = ( (a%c)(b%c) )%c

2.(b/a)%c = b*(a)^(c-2)%c

fast power

The algorithm of fast exponentiation is a dead algorithm, write it down after understanding the code.

Quick Power:

int POW(int a,int b){
    int ans = 1;
    int base = a;
    while(b){
        if(b & 1) ans *= base;
        base *= base;
        b >>= 1;
    }
    return ans;
}

Fast exponentiation (modulo):

int pow_mod(int a,int b,int c){
    int ans = 1;
    int base = a%c;
    while(b){
        if(b & 1) ans = (ans*base)%c;
        base = (base*base)%c;
        b >>= 1;
    }
    return ans;
}

GCD/Euclidean Algorithm

gcd is the greatest common divisor. To find the greatest common divisor, the simpler method is the method of rolling and dividing, also known as the Euclidean algorithm . Divide the larger number by the smaller number, then divide the divisor by the remainder (first remainder) that appears, and then divide the first remainder by the remainder (second remainder) that appears, and repeat until the final remainder is 0 . If you are looking for the greatest common divisor of two numbers, then the final divisor is the greatest common divisor of the two numbers.

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

Extended Euclid

very good article

For two integers a and b that are not all 0, there must be a set of solutions x, y such that ax+by==gcd(a,b);---------1 formula

Code


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

From this, expand ax+by==c, what should be its solution? x1=x(c/gcd(a,b)), y1=y(c/gcd(a,b)). (where x, y are the x and y obtained in formula 1)

The general solution of this formula x = x1+t*b/d,

y = y1-t*a/d. (t is any real number)

prime number sieve

reference

Essiere sieve

​ The method is actually very simple, first write down the integers in the range of 2 to n, where 2 is the smallest prime number. Cross out all the multiples of 2 in the table, and the smallest number left in the table is 3, which cannot be divided by smaller numbers, so 3 is a prime number. Then cross out all the multiples of 3 in the table... and so on, if the smallest remaining number in the table is m, then m is a prime number. Then cross out all the multiples of m in the table, and repeatedly operate like this, you can enumerate the prime numbers within n in turn, and the time complexity is O(nloglogn).

Code:

bool vis[maxn] = {0};//数值为0时代表是素数
int prime[maxn] = {0},x = 0;
void isprime(int n) 
{
    
    for(int i=2;i<=n;i++)
    {
        if(!vis[i]) prime[x++]=i;
        for(int j=2;j*i<=n;j++)
        {
            vis[i*j]=true;
        }
    }
}

Euler sieve

On the basis of the Esperanto sieve method, let each composite number be screened only once by its smallest prime factor, so as to achieve the purpose of non-repetition. Other complexity (O(n)).

Code

bool vis[maxn] = {0};//数值为0时代表是素数
int prime[maxn] = {0},x = 0;
void oulasai(int n)  //欧拉筛
{
    for(int i=2;i<=n;i++)
    {
        if(!vis[i]) prime[x++]=i;
        for(int j=0;j<x;j++)
        {
            if(i*prime[j]>n) break;
            vis[i*prime[j]]=true;
            if(i%prime[j]==0) break;
        }
    }
}

example

A/B

(A/B)%9973 is required, but since A is very large, we only give n(n=A%9973) (the A we give must be divisible by B, and gcd(B,9973) = 1).

Input

The first row of data is a T, indicating that there are T sets of data.
Each set of data has two numbers n(0 <= n < 9973) and B(1 <= B <= 10^9).

Output

Corresponding to each set of data output (A/B)%9973.

Sample Input

2
1000 53
87 123456789

Sample Output

7922
6060

untie:

If you want to write this question, you must know these formulas, (ab)%m = ( (a%m)(b%m) )%m,(a/b)%m = a*b^(m -2)%m;

So in the title (A/B)%9973 = A*B^(9971)%9973 = ( (A%9973)(B^(9971)%9973) )%9973 = ( n(B^(9971)%9973 ) )%9973;

Here we need to take the modulus of B (9971). If B (9971) is calculated first, it will obviously not work, and it will explode, so the algorithm of exponentiation modulo is used. Here I use fast exponentiation modulo.

ac code

#include<cstdio>
#include<iostream>
using namespace std;
int powmod(int a,int b,int c){//快速幂取模
    int ans = 1;
    int base = a%c;
    while(b){
        if(b & 1) ans = (ans*base)%c;
        base = (base*base)%c;
        b >>= 1;
    }
    return ans;
}
int main(){
	int t,n,b,ans;
	scanf("%d",&t);
	while(t--){
		scanf("%d %d",&n,&b);
		ans = (n*powmod(b,9971,9973) )%9973;
		printf("%d\n",ans);
	}
	return 0;
}

Frog Dating

topic link

Two frogs met online and had a great time chatting, so they felt the need to meet. They were delighted to find that they lived on the same line of latitude, so they agreed to each jump westward until they met. But before they set off, they forgot a very important thing. They neither asked about each other's characteristics, nor agreed on a specific location to meet. But the frogs are very optimistic. They feel that as long as they keep jumping in a certain direction, they will always meet each other. But unless the two frogs jump to the same point at the same time, they will never meet. In order to help these two optimistic frogs, you are asked to write a program to determine whether and when the two frogs can meet.
We call these two frogs Frog A and Frog B respectively, and stipulate that the origin is at 0 degrees east longitude on the latitude line, the positive direction is from east to west, and the unit length is 1 meter, so we get a number axis that is connected end to end . Let the coordinates of the starting point of frog A be x, and the coordinates of the starting point of frog B be y. Frog A can jump m meters at a time, frog B can jump n meters at a time, and it takes the same time for the two frogs to jump once. The total length of the latitude line is L meters. Now you need to find out how many times they jump before they meet.

Input

The input only includes a row of 5 integers x, y, m, n, L, where x≠y < 2000000000, 0 < m, n < 2000000000, 0 < L < 2100000000.

Output

Output the number of jumps required to meet, or output a line "Impossible" if it is never possible to meet

Sample Input

1 2 3 4 5

Sample Output

4

untie:

We can first assume that they meet after t, if they meet, the formula (x+mt)-(y+nt) = kl will be established, and the formula can be converted to (nm)t+lk = xy;

This just fits the extended Euclid's formula ax+by = c.

ac code

#include<cstdio>
#include<iostream>
using namespace std;
long long n,m,x,y,l,xx,yy;
long long a,b,c,d,t;
long long exgcd(long long a, long long b, long long &xx, long long &yy) {
    if (b == 0) {
        xx = 1;
        yy = 0;
        return a;
    }
    long long r = exgcd(b, a%b, xx, yy);
    long long t = xx; xx = yy; yy = t - a/b*yy;
    return r;
}
int main(){
	//long long n,m,x,y,l;
	
	scanf("%lld %lld %lld %lld %lld",&x,&y,&m,&n,&l);
	c = x - y;
	a = n - m;
	b = l;
	d = exgcd(a,b,xx,yy);
	//printf("%lld %lld\n",xx,yy);
	if(c%d!=0){
		printf("Impossible\n");
		return 0;
	}
	xx = xx*(c/d);yy = yy*(c/d);
	t = xx*d/b;//x = x1+t*b/d,因为t为任意实数所以令t = -t,令x等于0,解出t = x1*d/b。
	xx = xx - t*b/d;
	if(xx<0) xx+=(b/d);x//xx只能是正数。
	printf("%lld",xx);
	return 0;
}

beautiful primes

Xiao Ming loves the study of numbers. When it comes to numbers, many questions pop up in his mind. Today, Xiao Ming wants to test your knowledge of prime numbers.
  The problem is this: if a decimal number is a prime number and the sum of its digits is also a prime number, it is called a "beautiful prime number", such as 29, which itself is a prime number, and 2+9 = 11 is also a prime number, so it is Beauty primes.
  Given an interval, can you count how many primes are in this interval?

Input

The first line enters a positive integer T, indicating that there are T sets of data in total (T <= 10000).
There are T lines in the next, and each line enters two integers L, R (1<= L <= R <= 1000000), indicating the left value and right value of the interval.

Output

For each set of data, first output the Case number, and then output the number of prime numbers in the interval (including the endpoint values ​​L, R).
Each set of data occupies one line, see the sample for the specific output format.

Sample Input

3
1 100
2 2
3 19

Sample Output

Case #1: 14
Case #2: 1
Case #3: 4

untie:

According to the meaning of the title, first use the sieve method to sieve out the prime numbers, and then calculate the number. But we found that this will time out, so we need to do a preprocessing, use the array s[i] to store the answer, s[i] represents the number of prime numbers in 1-i, so we know the answer is s[ r]-s[l-1].

ac code

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
#define maxn 1000000
bool vis[maxn+5] = {0};
int prime[maxn+5] = {0},x = 0;
int s[maxn+5] = {0};
void osai(int n){//欧拉筛
	int i,j;
	for(i = 2;i<=n;i++){
		if(!vis[i]) prime[x++] = i;
		for(j = 0;j<x;j++){
			if(i*prime[j]>n) break;
			vis[i*prime[j]] = 1;
			if(i%prime[j] == 0) break;
		}
	}
}

int change(int n){//求各位数之和
	int sum = 0;
	while(n){
		sum+=n%10;
		n/=10;
	}
	return sum;
}

int main(){
	int t,l,r,count,i,j;
	osai(1000003);
	vis[1] = 1;
	for(i = 1;i<=1000000;i++){//预处理
		s[i] = s[i-1];
		if(vis[i] == 0&&vis[change(i)] == 0) s[i]++;
	}
	scanf("%d",&t);
	for(j = 1;j<=t;j++){
		count = 0;
		scanf("%d %d",&l,&r);
		printf("Case #%d: %d\n",j,s[r]-s[l-1]);
	}
	return 0;
}

Guess you like

Origin blog.csdn.net/m0_51687577/article/details/113836141