[number theory series I] C Looooops, checkers, the lucky number, cf906d, power tower, minimum power of prime, guard of honor, LCMSUM

Posted by HektoR on Tue, 18 Jan 2022 07:44:38 +0100

All the number theory knowledge involved below proves portal 1

All the number theory knowledge involved below proves Portal 2

C Looooops

description

solution

Transform the meaning of the question into a mathematical formula A + C x ≡ B ( m o d 2 k ) A+Cx\equiv B\pmod {2^k} A+Cx ≡ B(mod2k), and finally find the minimum x x x

In fact, removing the mold taking operation is an extension of the very template Euclid, C ⋅ x − y ⋅ 2 k = B − A C·x-y·2^k=B-A C⋅x−y⋅2k=B−A

First find a set of special solutions, and then find the minimum positive integer x x x (please send the minimum solution to the certification chapter)

code

#include <cmath>
#include <cstdio>
#include <iostream>
using namespace std;
#define int long long

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

signed main() {
	int A, B, C, k;
	while( scanf( "%lld %lld %lld %lld", &A, &B, &C, &k ) ) {
		if( ! A && ! B && ! C && ! k ) break;
		int a = C, b = 1ll << k, c = B - A, x, y;
		int d = exgcd( a, b, x, y );
		if( c % d ) {
			printf( "FOREVER\n" );
			continue;
		}
		x = ( x * ( c / d ) % ( b / d ) + ( b / d ) ) % ( b / d );
		printf( "%lld\n", x );
	}
	return 0;
}

Checkers

description

solution

The key to this question is that only one chess piece is allowed to be skipped at a time

That is, for the chess pieces in the middle, only the closest chess pieces have the right to jump

a,b,c → \rightarrow →b,2b-a,c/a,2b-c,b

If will ( a , b , c ) (a,b,c) (a,b,c) is regarded as a point, then a point can only have two successors

Build a binary tree, jump all relative to the middle chess pieces, reduce the distance of three balls until they are equal, and define such points as the root of the tree

To judge that there is no solution, you only need to see whether the initial situation and the end situation belong to the same node after operating according to the above rules

Jumping once is to climb a layer on the tree. You can't climb step by step, but jump to a point with a shorter distance at one time, and then jump on the other side

Then count how many steps the situation jumps in this process, that is, the corresponding depth

Jump the initial situation and the end situation to the same level first, and then find the depth of two-point jump l c a lca lca (same for both sides)

code

#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
#define int long long
#define inf 1e18
struct node {
	int pos[5];
	bool operator != ( const node &t ) const {
		for( int i = 1;i <= 3;i ++ )
			if( pos[i] != t.pos[i] ) return 1;
		return 0;
	}
}S, E;
int dep_S, dep_E, dep;
int Sp[5], Ep[5];

node solve( int MS[], int len ) {
	node ans;
	for( int i = 1;i <= 3;i ++ )
		ans.pos[i] = MS[i];
	int d1 = MS[2] - MS[1], d2 = MS[3] - MS[2];
	if( d1 == d2 ) return ans;
	else if( d1 < d2 ) {
		int k = min( len, ( d2 - 1 ) / d1 );
		len -= k, dep += k;
		ans.pos[1] += k * d1;
		ans.pos[2] += k * d1;
	}
	else {
		int k = min( len, ( d1 - 1 ) / d2 );
		len -= k, dep += k;
		ans.pos[2] -= k * d2;
		ans.pos[3] -= k * d2;
	}
	if( len ) return solve( ans.pos, len );
	else return ans;
}

signed main() {
	for( int i = 1;i <= 3;i ++ )
		scanf( "%lld", &Sp[i] );
	for( int i = 1;i <= 3;i ++ )
		scanf( "%lld", &Ep[i] );
	sort( Sp + 1, Sp + 4 );
	sort( Ep + 1, Ep + 4 );
	S = solve( Sp, inf );
	dep_S = dep;
	dep = 0;
	E = solve( Ep, inf );
	dep_E = dep;
	dep = 0;
	if( S != E ) return ! printf( "NO\n" );
	else printf( "YES\n" );
	if( dep_S > dep_E ) {
		swap( dep_S, dep_E );
		for( int i = 1;i <= 3;i ++ )
			swap( Sp[i], Ep[i] );
	}
	int ans = dep_E - dep_S;
	if( ans ) {
		E = solve( Ep, ans );
		for( int i = 1;i <= 3;i ++ )
			Ep[i] = E.pos[i];
	}
	int l = 0, r = dep_S;
	while( l < r ) {
		int mid = ( l + r ) >> 1;
		if( solve( Sp, mid ) != solve( Ep, mid ) ) l = mid + 1;
		else r = mid;
	}
	printf( "%lld\n", ans + l * 2 );
	return 0;
}

The Luckiest number

description

solution

L ∣ 8 ∗ 1 0 n − 1 9 ⇔ 9 ∗ L gcd ⁡ ( 8 , L ) ∣ ( 10 n − 1 ) ∗ 8 gcd ⁡ ( 8 , L ) L\bigg|8*\frac{10^n-1}{9}\Leftrightarrow \frac{9*L}{\gcd(8,L)}\bigg|\frac{(10n-1)*8}{\gcd(8,L)} L∣∣∣∣​8∗910n−1​⇔gcd(8,L)9∗L​∣∣∣∣​gcd(8,L)(10n−1)∗8​

∵ gcd ⁡ ( 8 , 9 ) = 1 \because \gcd(8,9)=1 ∵gcd(8,9)=1

∴ 10 n ≡ 1 ( m o d 9 L gcd ⁡ ( 8 , L ) ) \therefore 10n\equiv 1\pmod{\frac{9L}{\gcd(8,L)}} ∴10n≡1(modgcd(8,L)9L​)

No solution, i.e gcd ⁡ ( 10 , 9 L gcd ⁡ ( 8 , L ) ) = 1 \gcd(10,\frac{9L}{\gcd(8,L)})=1 gcd(10,gcd(8,L)9L​)=1

Otherwise, convert to a x ≡ 1 ( m o d m ) a^x\equiv 1\pmod m ax ≡ 1(modm), find the minimum x x x

According to the formula of order x ∣ ϕ ( m ) x\bigg|\phi(m) x∣∣∣∣​ϕ(m)

Direct enumeration calculation

code

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
#define int long long

int gcd( int x, int y ) {
	if( ! y ) return x;
	else return gcd( y, x % y );
}

int calc( int x ) {
	int ans = x;
	for( int i = 2;i * i <= x;i ++ )
		if( x % i == 0 ) {
			ans = ans / i * ( i - 1 );
			while( x % i == 0 ) x /= i;
		}
	if( x != 1 ) ans = ans / x * ( x - 1 );
	return ans;
}

int qkmul( int x, int y, int mod ) {
	int ans = 0;
	while( y ) {
		if( y & 1 ) ans = ( ans + x ) % mod;
		x = ( x + x ) % mod;
		y >>= 1;
	}
	return ans;
}

int qkpow( int x, int y, int mod ) {
	int ans = 1;
	while( y ) {
		if( y & 1 ) ans = qkmul( ans, x, mod );
		x = qkmul( x, x, mod );
		y >>= 1;
	}
	return ans;
}

signed main() {
	int L;
	for( int T = 1;;T ++ ) {
		scanf( "%lld", &L );
		if( ! L ) return 0;
		L *= 9;
		for( int i = 1;i <= 3;i ++ )
			if( L % 2 == 0 ) L >>= 1;
			else break;
		if( gcd( 10, L ) != 1 ) {
			printf( "Case %lld: 0\n", T );
			continue;
		}
		int phi = calc( L ), ans = L;
		for( int i = 1;i * i <= phi;i ++ )
			if( phi % i ) continue;
			else {
				if( qkpow( 10, i, L ) == 1 ) {
					ans = i;
					break;
				}
				else if( qkpow( 10, phi / i, L ) == 1 )
					ans = min( ans, phi / i );
			}
		printf( "Case %lld: %lld\n", T, ans );
	}
	return 0;
}

CF906D Power Tower

description

solution

Board problems of extended Euler theorem
x r ≡ { x r r < m x r % ϕ ( m ) ( x , m ) = 1 x r % ϕ ( m ) + ϕ ( m ) ( x , m ) > 1 x^r\equiv \begin{cases} x^r&&r<m\\ x^{r\%\phi(m)}&&(x,m)=1\\ x^{r\%\phi(m)+\phi(m)}&&(x,m)>1 \end{cases} xr≡⎩⎪⎨⎪⎧​xrxr%ϕ(m)xr%ϕ(m)+ϕ(m)​​r<m(x,m)=1(x,m)>1​
Iterative calculation index, current layer m o d mod mod ϕ ( m o d ) \phi(mod) ϕ (mod) is the next level of its index m o d ′ mod' mod′

code

#include <iostream> 
#include <cstdio>
using namespace std;

#if(__cplusplus == 201103L)
#include <unordered_map>
#else
#include <tr1/unordered_map>
namespace std
{
    using std::tr1::unordered_map;
}
#endif

#define int long long
#define maxn 100005
unordered_map < int, int > mp;
int l, r;
int w[maxn];

int E( int x, int mod ) {
	return x < mod ? x : x % mod + mod;
}

int qkpow( int x, int y, int mod ) {
	int ans = 1;
	while( y ) {
		if( y & 1 ) ans = E( ans * x, mod );
		x = E( x * x, mod );
		y >>= 1;
	}
	return ans;
}

int phi( int n ) {
	if( mp.count( n ) ) return mp[n];
	int ans = n, x = n;
	for( int i = 2;i * i <= x;i ++ )
		if( x % i == 0 ) {
			ans = ans / i * ( i - 1 );
			while( x % i == 0 ) x /= i;
		}
	if( x != 1 ) ans = ans / x * ( x - 1 );
	return mp[n] = ans;
}

int solve( int d, int pos, int mod ) {
	if( pos == r + 1 || mod == 1 ) return E( d, mod );
	int p = phi( mod );
	int e = solve( w[pos], pos + 1, p );
	return qkpow( d, E( e, p ), mod );
}

signed main() {
	int n, mod, Q;
	scanf( "%lld %lld", &n, &mod );
	for( int i = 1;i <= n;i ++ )
		scanf( "%lld", &w[i] );
	scanf( "%lld", &Q );
	while( Q -- ) {
		scanf( "%lld %lld", &l, &r );
		printf( "%lld\n", solve( w[l], l + 1, mod ) % mod );
	}
}

Minimal Power of Prime

description

solution

An integer standard unique decomposition problem with a large data range

Trial division method

Use no more than n 1 5 n^\frac{1}{5} Prime number removal to the power of n51 n n n. So n n n up to four prime factors remain

Conditional statements are discussed vigorously, n n If n is not a second power / third power / fourth power, it must belong to the case that at least one is a first power

code

#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
#define maxn 1000000
#define int long long
int T, n, cnt;
bool vis[maxn];
int prime[maxn];

void sieve() {
	for( int i = 2;i < maxn;i ++ ) {
		if( ! vis[i] ) vis[i] = 1, prime[++ cnt] = i;
		for( int j = 1;j <= cnt && i * prime[j] < maxn;j ++ ) {
			vis[i * prime[j]] = 1;
			if( i % prime[j] == 0 ) break;
		}
	}
}

int calc( int x, int t ) {
	int ans = 1;
	for( int i = 1;i <= t;i ++ )
		ans *= x;
	return ans;
}

signed main() {
	sieve();
	scanf( "%lld", &T );
	while( T -- ) {
		scanf( "%lld", &n );
		int m = powl( n, 1.0 / 5 ), ans = n;
		for( int i = 1;i <= cnt;i ++ )
			if( prime[i] > m ) break;
			else if( n % prime[i] == 0 ) {
				int tot = 0;
				while( n % prime[i] == 0 )
					tot ++, n /= prime[i];
				ans = min( ans, tot );
			}
		int x = powl( n, 1.0 / 4 );
		int y = powl( n, 1.0 / 3 );
		int z = powl( n, 1.0 / 2 );
		if( n == 1 ) goto print;
		if( calc( x, 4 ) == n || calc( x - 1, 4 ) == n || calc( x + 1, 4 ) == n )
			ans = min( ans, 4ll );
		else if( calc( y, 3 ) == n || calc( y - 1, 3 ) == n || calc( y + 1, 3 ) == n )
			ans = min( ans, 3ll );
		else if( calc( z, 2 ) == n || calc( z - 1, 2 ) == n || calc( z + 1, 2 ) == n )
			ans = min( ans, 2ll );
		else
			ans = min( ans, 1ll );
		print : 
			printf( "%lld\n", ans );
	}
	return 0;
}

[SDOI2008] guard of honor

description

solution

Define the coordinates of each point as ( x − 1 , y − 1 ) (x-1,y-1) (x − 1,y − 1), then C C C Jun is right there ( 0 , 0 ) (0,0) (0,0) position

Consider the properties of the point coordinates of the children that can be seen

According to the fact that a line can be characterized by a vector, let ( x , y ) (x,y) (x,y) if the child can be seen, then the child on this straight line λ > 1 , ( λ x , λ y ) \lambda>1,(\lambda x,\lambda y) λ> 1,( λ x, λ y) Will be blocked

And gcd ⁡ ( λ x , λ y ) = λ ( x , y ) ≥ λ > 1 \gcd(\lambda x,\lambda y)=\lambda(x,y)\ge \lambda>1 gcd(λx,λy)=λ(x,y)≥λ>1

That is, if gcd ⁡ ( x , y ) > 1 \gcd(x,y)>1 GCD (x, y) > 1 the child will be blocked

If gcd ⁡ ( x , y ) = 1 \gcd(x,y)=1 Children with gcd(x,y)=1 will be blocked, then they must exist ( x μ , y μ ) , μ > 1 (\frac{x}{\mu},\frac{y}{\mu}),\mu>1 ( μ x​, μ y​), μ> 1 children exist, obviously there is no such point

To sum up, it can be seen only when the children's abscissa and ordinate are coprime

Translated into mathematical language, i.e.: a n s = ∑ i = 0 n − 1 ∑ j = 0 n − 1 [ gcd ⁡ ( i , j ) = 1 ] ans=\sum_{i=0}^{n-1}\sum_{j=0}^{n-1}\Big[\gcd(i,j)=1\Big] ans=∑i=0n−1​∑j=0n−1​[gcd(i,j)=1]

⇔ ∑ i = 0 n − 1 ∑ j = 0 i − 1 [ gcd ⁡ ( i , j ) = 1 ] + ∑ i = 0 n − 1 ∑ j = i i [ gcd ⁡ ( i , j ) = 1 ] + ∑ i = 0 n − 1 ∑ j = i + 1 n − 1 [ gcd ⁡ ( i , j ) = 1 ] \Leftrightarrow \sum_{i=0}^{n-1}\sum_{j=0}^{i-1}\Big[\gcd(i,j)=1\Big]+\sum_{i=0}^{n-1}\sum_{j=i}^i\Big[\gcd(i,j)=1\Big]+\sum_{i=0}^{n-1}\sum_{j=i+1}^{n-1}\Big[\gcd(i,j)=1\Big] ⇔∑i=0n−1​∑j=0i−1​[gcd(i,j)=1]+∑i=0n−1​∑j=ii​[gcd(i,j)=1]+∑i=0n−1​∑j=i+1n−1​[gcd(i,j)=1]

∑ i = 0 n − 1 ∑ j = i i [ gcd ⁡ ( i , j ) = 1 ] \sum_{i=0}^{n-1}\sum_{j=i}^i\Big[\gcd(i,j)=1\Big] Σ i=0n − 1 Σ j=ii [gcd(i,j)=1] represents y = x y=x y=x straight line, obviously only one child can be seen, and then it can be deleted

n × n n\times n n × Graph of N, C C C Jun is at the origin. The hidden nature is what the children see about y = x y=x y=x linear symmetry

The formula continues to be 2 ( ∑ i = 0 n − 1 ∑ j = 0 i − 1 [ gcd ⁡ ( i , j ) = 1 ] ) 2\bigg(\sum_{i=0}^{n-1}\sum_{j=0}^{i-1}\Big[\gcd(i,j)=1\Big]\bigg) 2(∑i=0n−1​∑j=0i−1​[gcd(i,j)=1])

Surprisingly, it is found that the value range and requirements of the inner loop fully comply with the Euler function φ \varphi φ Definition of

So the final answer is 1 + 2 ∑ i = 0 n − 1 φ ( i ) 1+2\sum_{i=0}^{n-1}\varphi(i) 1+2∑i=0n−1​φ(i)

code

#include <cstdio>
#define maxn 40005
int prime[maxn], phi[maxn];
bool vis[maxn];
int n;

void sieve() {
	phi[1] = 1; int cnt = 0;
	for( int i = 2;i <= n;i ++ ) {
		if( ! vis[i] ) prime[++ cnt] = i, phi[i] = i - 1;
		for( int j = 1;j <= cnt && i * prime[j] <= n;j ++ ) {
			vis[i * prime[j]] = 1;
			if( i % prime[j] == 0 ) {
				phi[i * prime[j]] = phi[i] * prime[j];
				break;
			}
			else
				phi[i * prime[j]] = phi[i] * ( prime[j] - 1 );
		}
	}
}

int main() {
	scanf( "%d", &n );
	if( n == 1 ) return ! printf( "0\n" );
	sieve();
	int ans = 0;
	for( int i = 0;i < n;i ++ )
		ans += ( phi[i] << 1 );
	printf( "%d\n", ans + 1 );
}

LCMSUM

description

solution

∑ i = 1 n lcm ⁡ ( i , j ) ⇔ ∑ i = 1 n i × n gcd ⁡ ( i , n ) \sum_{i=1}^n \operatorname{lcm}(i,j)\Leftrightarrow \sum_{i=1}^n\frac{i\times n}{\operatorname{gcd}(i,n)} ∑i=1n​lcm(i,j)⇔∑i=1n​gcd(i,n)i×n​

∵ gcd ⁡ ( i , n ) = gcd ⁡ ( n − i , n ) \because \gcd(i,n)=\gcd(n-i,n) ∵ gcd(i,n)=gcd(n − i,n), two by two gcd ⁡ \gcd gcd same merge i + ( n − i ) = n i+(n-i)=n i+(n−i)=n

1 2 ( ∑ i = 1 n − 1 i ∗ n gcd ⁡ ( i , n ) + ∑ i = n − 1 1 i ∗ n gcd ⁡ ( i , n ) ) + lcm ⁡ ( n , n ) = n + 1 2 ∑ i = 1 n − 1 n 2 gcd ⁡ ( i , j ) \frac{1}{2}\Big(\sum_{i=1}^{n-1}\frac{i*n}{\gcd(i,n)}+\sum_{i=n-1}^1\frac{i*n}{\gcd(i,n)}\Big)+\operatorname{lcm}(n,n)=n+\frac{1}{2}\sum_{i=1}^{n-1}\frac{n^2}{\gcd(i,j)} 21​(∑i=1n−1​gcd(i,n)i∗n​+∑i=n−11​gcd(i,n)i∗n​)+lcm(n,n)=n+21​∑i=1n−1​gcd(i,j)n2​

gcd ⁡ ( i , n ) = d \gcd(i,n)=d gcd(i,n)=d i i The number of i is ϕ ( n d ) \phi(\frac{n}{d}) ϕ (dn) Nos ( g c d ( i d , n d ) = 1 \Big(gcd(\frac{i}{d},\frac{n}{d})=1 (the number of gcd(di, dn) = 1 is ϕ ( n d ) ) \phi(\frac{n}{d})\Big) ϕ(dn​))

⇒ n + 1 2 ∑ i = 1 n − 1 n 2 gcd ⁡ ( i , j ) = n + 1 2 ∑ d ∣ n n 2 ⋅ ϕ ( n d ) d = n + 1 2 ∑ d ∣ n n 2 ⋅ ϕ ( d ) n d \Rightarrow n+\frac{1}{2}\sum_{i=1}^{n-1}\frac{n^2}{\gcd(i,j)}=n+\frac{1}{2}\sum_{d\big|n}\frac{n^2·\phi(\frac{n}{d})}{d}=n+\frac{1}{2}\sum_{d\big|n}n^2·\frac{\phi(d)}{\frac{n}{d}} ⇒n+21​∑i=1n−1​gcd(i,j)n2​=n+21​∑d∣∣​n​dn2⋅ϕ(dn​)​=n+21​∑d∣∣​n​n2⋅dn​ϕ(d)​

= n + n ∑ d ∣ n d ⋅ ϕ ( d ) 2 =n+n\sum_{d\big|n}\frac{d·\phi(d)}{2} =n+n∑d∣∣​n​2d⋅ϕ(d)​

Linear sieve pretreatment

code

#include <cstdio>
#define maxn 1000000
#define int long long
int prime[maxn + 5], phi[maxn + 5], sum[maxn + 5];
bool vis[maxn + 5];

void sieve() {
	phi[1] = 1; int cnt = 0;
	for( int i = 2;i <= maxn;i ++ ) {
		if( ! vis[i] ) prime[++ cnt] = i, phi[i] = i - 1;
		for( int j = 1;j <= cnt && i * prime[j] <= maxn;j ++ ) {
			vis[i * prime[j]] = 1;
			if( i % prime[j] == 0 ) {
				phi[i * prime[j]] = phi[i] * prime[j];
				break;
			}
			else
				phi[i * prime[j]] = phi[i] * ( prime[j] - 1 );
		}
	}
	for( int i = 1;i <= maxn;i ++ )
		for( int j = 1;i * j <= maxn;j ++ )
			sum[i * j] += i * phi[i] / 2;
	for( int i = 1;i <= maxn;i ++ )
		sum[i] = sum[i] * i + i;
}

signed main() {
	sieve();
	int T, n;
	scanf( "%lld", &T );
	while( T -- ) {
		scanf( "%lld", &n );
		if( n == 1 ) printf( "1\n" );
		else printf( "%lld\n", sum[n] );
	}
	return 0;
}

Topics: number theory Math