8.7 数论专题
P5656 【模板】二元一次不定方程 (exgcd)
可以先用
然后再搞出最小的正整数
最后通过
#include <bits/stdc++.h>
using namespace std;
#define mid (l+r>>1)
#define endl '\n'
#define inl inline
#define int long long
const int inf = 0x3f3f3f3f;
const int N = 5e5 + 5;
char buf[1<<24] , *p1 , *p2;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<24,stdin),p1==p2)?EOF:*p1++)
//#define getchar() cin.get();
int read()
{
int x = 0 , f = 1;
char ch = getchar();
while ( !isdigit(ch) ) { if ( ch == '-' ) f = -1; ch = getchar(); }
while ( isdigit(ch) ) { x = ( x << 1 ) + ( x << 3 ) + ( ch ^ 48 ); ch = getchar(); }
return x * f ;
}
int n , m;
int gcd ( int a , int b )
{
if ( a % b == 0 ) return b;
return gcd ( b , a % b );
}
void exgcd ( int a , int b , int &x, int &y )
{
if ( !b ) return x = 1 , y = 0 , void();
exgcd ( b , a % b , y , x ) , y -= ( a / b ) * x;
}
signed main ()
{
ios::sync_with_stdio(false);
cin.tie(nullptr) , cout.tie(nullptr);
int T = read();
while ( T -- )
{
int a = read() , b = read() , c = read() , x = 0 , y = 0 , cnt = 0 , xmin , xmax , ymin , ymax;
int g = gcd ( a , b );
if ( c % g ^ 0 ) { cout << -1 << endl; continue; }
a /= g , b /= g , c /= g , exgcd ( a , b , x , y );
x *= c , y *= c; // 求出一组特解
xmin = ( x > 0 && x % b != 0 ) ? x % b : x % b + b;
ymax = ( c - xmin * a ) / b;
ymin = ( y > 0 && y % a != 0 ) ? y % a : y % a + a;
xmax = ( c - ymin * b ) / a;
if ( xmax > 0 ) cnt = ( xmax - xmin ) / b + 1;
if ( cnt ) cout << cnt << ' ' << xmin << ' ' << ymin << ' ' << xmax << ' ' << ymax << endl;
else cout << xmin << ' ' << ymin << endl;
}
return 0;
}
Enlarge GCD
首先我们消除原来的
所以我们可以用埃筛的性质 从小到大枚举质数作为这个
值域
#include <bits/stdc++.h>
using namespace std;
#define mid (l+r>>1)
#define endl '\n'
#define inl inline
#define ls(p) t[p].son[0]
#define rs(p) t[p].son[1]
#define lson ls(p),l,mid
#define rson rs(p),mid+1,r
#define eb emplace_back
const int N = 1.5e7 + 5;
const int inf = 0x3f3f3f3f;
//char buf[1<<24] , *p1 , *p2;
//#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<24,stdin),p1==p2)?EOF:*p1++)
#define getchar() cin.get();
int read()
{
int x = 0 , f = 1;
char ch = getchar();
while ( !isdigit(ch) ) { if ( ch == '-' ) f = -1; ch = getchar(); }
while ( isdigit(ch) ) { x = ( x << 1 ) + ( x << 3 ) + ( ch ^ 48 ); ch = getchar(); }
return x * f ;
}
int n , a[N] , ans = inf , maxx , vis[N] , cnt[N];
int gcd ( int a , int b )
{
if ( a % b == 0 ) return b;
return gcd ( b , a % b );
}
signed main ()
{
ios::sync_with_stdio(false);
cin.tie(nullptr) , cout.tie(nullptr);
n = read();
for ( int i = 1 ; i <= n ; i ++ ) a[i] = read();
int gcdd = a[1];
for ( int i = 2 ; i <= n ; i ++ ) gcdd = gcd ( gcdd , a[i] );
for ( int i = 1 ; i <= n ; i ++ ) a[i] /= gcdd , cnt[a[i]] ++ , maxx = max ( a[i] , maxx );
for ( int i = 2 ; i <= maxx ; i ++ )
{
int res = 0;
if ( !vis[i] ) for ( int j = 1 ; j <= maxx / i ; j ++ ) vis[i*j] = 1 , res += cnt[i*j];
ans = min ( ans , n - res );
}
cout << ( ans == inf ? -1 : ans ) << endl;
return 0;
}
P2265 路边的水沟
因为我们从走对角线的长度就是曼哈顿距离
组合数即可
#include <bits/stdc++.h>
using namespace std;
#define mid (l+r>>1)
#define endl '\n'
#define inl inline
#define ls(p) t[p].son[0]
#define rs(p) t[p].son[1]
#define lson ls(p),l,mid
#define rson rs(p),mid+1,r
#define eb emplace_back
#define int long long
const int N = 1e6 + 5;
const int maxn = 1e6;
const int mod = 1e9 + 7;
char buf[1<<24] , *p1 , *p2;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<24,stdin),p1==p2)?EOF:*p1++)
//#define getchar() cin.get();
int read()
{
int x = 0 , f = 1;
char ch = getchar();
while ( !isdigit(ch) ) { if ( ch == '-' ) f = -1; ch = getchar(); }
while ( isdigit(ch) ) { x = ( x << 1 ) + ( x << 3 ) + ( ch ^ 48 ); ch = getchar(); }
return x * f ;
}
int n , m , inv[N] , fac[N] , ifac[N];
void init()
{
ifac[0] = ifac[1] = inv[1] = fac[0] = fac[1] = 1;
for ( int i = 2 ; i <= maxn ; i ++ )
{
fac[i] = fac[i-1] * i % mod;
inv[i] = ( mod - mod / i ) * inv[mod%i] % mod;
ifac[i] = ifac[i-1] * inv[i] % mod;
}
}
int C ( int n , int m ) { return fac[n] * ifac[n-m] % mod * ifac[m] % mod; }
signed main ()
{
ios::sync_with_stdio(false);
cin.tie(nullptr) , cout.tie(nullptr);
n = read() , m = read();
init();
cout << C ( n + m , m ) << endl;
return 0;
}
P3868 [TJOI2009] 猜数字
标准的
#include <bits/stdc++.h>
using namespace std;
#define mid (l+r>>1)
#define endl '\n'
#define inl inline
#define eb emplace_back
#define int __int128
const int N = 15 + 5;
char buf[1<<24] , *p1 , *p2;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<24,stdin),p1==p2)?EOF:*p1++)
//#define getchar() cin.get();
int read()
{
int x = 0 , f = 1;
char ch = getchar();
while ( !isdigit(ch) ) { if ( ch == '-' ) f = -1; ch = getchar(); }
while ( isdigit(ch) ) { x = ( x << 1 ) + ( x << 3 ) + ( ch ^ 48 ); ch = getchar(); }
return x * f ;
}
int n , M = 1 , a[N] , b[N] , k[N] , ans;//余数 模数
void exgcd ( int aa , int bb , int &x , int &y )
{
if ( !bb ) return x = 1 , y = 0 , void();
exgcd ( bb , aa % bb , y , x ) , y -= aa / bb * x;
}
signed main ()
{
ios::sync_with_stdio(false);
cin.tie(nullptr) , cout.tie(nullptr);
n = read();
for ( int i = 1 ; i <= n ; i ++ ) a[i] = read();
for ( int i = 1 ; i <= n ; i ++ ) b[i] = read() , M *= b[i];
for ( int i = 1 ; i <= n ; i ++ ) k[i] = M / b[i];
for ( int i = 1 ; i <= n ; i ++ )
{
int x = 0 , y = 0;
exgcd ( k[i] , b[i] , x , y );
ans = ( ( ans + k[i] * a[i] * x ) % M + M ) % M;
}
cout << (long long)ans << endl;
return 0;
}
欧拉函数
P2158 [SDOI2008] 仪仗队
对于一个
1110
1100
1000
0000
对于一个点
这个东西正好符合欧拉函数的定义 那么上半部分答案就是
对于欧拉函数的求法 可以线性筛求解 分三种情况:
为质数 与 互质 与 不互质
最后我们需要加上
完整代码:
#include <bits/stdc++.h>
using namespace std;
#define mid (l+r>>1)
#define endl '\n'
#define inl inline
#define eb emplace_back
const int N = 4e4 + 5;
char buf[1<<24] , *p1 , *p2;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<24,stdin),p1==p2)?EOF:*p1++)
//#define getchar() cin.get();
int read()
{
int x = 0 , f = 1;
char ch = getchar();
while ( !isdigit(ch) ) { if ( ch == '-' ) f = -1; ch = getchar(); }
while ( isdigit(ch) ) { x = ( x << 1 ) + ( x << 3 ) + ( ch ^ 48 ); ch = getchar(); }
return x * f ;
}
int ans , n , prime[N] , tot , p[N] , isntprime[N];
void phi()
{
p[1] = 1;
for ( int i = 2 ; i <= n ; i ++ )
{
if ( !isntprime[i] ) prime[++tot] = i , p[i] = i - 1;
for ( int j = 1 ; j <= tot && i * prime[j] <= n ; j ++ )
{
isntprime[i*prime[j]] = 1;
if ( i % prime[j] == 0 ) { p[i*prime[j]] = p[i] * prime[j]; break; }
else p[i*prime[j]] = p[i] * ( prime[j] - 1 );
}
}
}
signed main ()
{
ios::sync_with_stdio(false);
cin.tie(nullptr) , cout.tie(nullptr);
n = read();
phi();
for ( int i = 1 ; i < n ; i ++ ) ans += p[i];
cout << ( n != 1 ? ans * 2 + 1 : 0 ) << endl;
return 0;
}
P5091 【模板】扩展欧拉定理
欧拉定理:
当
这里
所以
扩展欧拉定理:
当
柿子:
枚举因数到
本题分析:
观察到
必须注意 如果
读入进合理范围的
#include <bits/stdc++.h>
using namespace std;
#define mid (l+r>>1)
#define endl '\n'
#define inl inline
#define eb emplace_back
#define int long long
char buf[1<<24] , *p1 , *p2;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<24,stdin),p1==p2)?EOF:*p1++)
//#define getchar() cin.get();
int read()
{
int x = 0 , f = 1;
char ch = getchar();
while ( !isdigit(ch) ) { if ( ch == '-' ) f = -1; ch = getchar(); }
while ( isdigit(ch) ) { x = ( x << 1 ) + ( x << 3 ) + ( ch ^ 48 ); ch = getchar(); }
return x * f ;
}
int read ( int mod )
{
int x = 0 , f = 0; char ch = getchar();
while ( !isdigit(ch) ) ch = getchar();
while ( isdigit(ch) ) { x = ( x << 1 ) + ( x << 3 ) + ( ch ^ 48 ); if ( x >= mod ) f = 1 , x %= mod; ch = getchar(); }
return x + (f?mod:0);
}
int a , b , m;
int phi ( int n )
{
int ans = n;
for ( int i = 2 ; i * i <= n ; i ++ )
if ( n % i == 0 )
{
ans = ans / i * ( i - 1 );
while ( n % i == 0 ) n /= i;
}
if ( n > 1 ) ans = ans / n * ( n - 1 );
return ans;
}
int ksm ( int base , int k , int mod )
{
int res = 1;
for ( ; k ; k >>= 1 , base = base * base % mod )
if ( k & 1 ) res = res * base % mod;
return res;
}
signed main ()
{
ios::sync_with_stdio(false);
cin.tie(nullptr) , cout.tie(nullptr);
a = read() , m = read();
b = read(phi(m));
cout << ksm ( a , b , m ) << endl;
return 0;
}
P4139 上帝与集合的正确用法
根据扩展欧拉定理 当
所以要求
#include <bits/stdc++.h>
using namespace std;
#define mid (l+r>>1)
#define endl '\n'
#define inl inline
#define eb emplace_back
const int N = 1e7 + 5;
const int maxn = 1e7;
char buf[1<<24] , *p1 , *p2;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<24,stdin),p1==p2)?EOF:*p1++)
//#define getchar() cin.get();
int read()
{
int x = 0 , f = 1;
char ch = getchar();
while ( !isdigit(ch) ) { if ( ch == '-' ) f = -1; ch = getchar(); }
while ( isdigit(ch) ) { x = ( x << 1 ) + ( x << 3 ) + ( ch ^ 48 ); ch = getchar(); }
return x * f ;
}
int ans , n , prime[N] , tot , p[N] , isntprime[N];
void phi ()
{
p[1] = 1;
for ( int i = 2 ; i <= maxn ; i ++ )
{
if ( !isntprime[i] ) prime[++tot] = i , p[i] = i - 1;
for ( int j = 1 ; j <= tot && i * prime[j] <= maxn ; j ++ )
{
isntprime[i*prime[j]] = 1;
if ( i % prime[j] == 0 ) { p[i*prime[j]] = p[i] * prime[j]; break; }
else p[i*prime[j]] = p[i] * ( prime[j] - 1 );
}
}
}
long long pow ( long long base , int k , int mod )
{
long long res = 1;
while ( k )
{
if ( k & 1 ) ( res *= base ) %= mod;
( base *= base ) %= mod;
k >>= 1;
}
return res;
}
int solve ( int x )
{
if ( x == 1 ) return 0;
return pow ( 2 , solve ( p[x] ) + p[x] , x );
}
signed main ()
{
ios::sync_with_stdio(false);
cin.tie(nullptr) , cout.tie(nullptr);
phi();
int T = read();
while ( T -- )
{
int x = read();
cout << solve(x) << endl;
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】