今天是來講數論的
(by 銻’s口胡,大佬輕拍)
1.Prime Distance(check here)
題目描述:給你一個L,一個R,求L-R中最近的兩個質數以及最遠的兩個質數。
範圍:
Solution:首先對於,非常的大,已知的所有篩法都無法在規定時間內求解。但是可以看到範圍裏還有很鬼畜的一條東西:。根據它我們可以看出來,我們是可以掃一遍的,考慮到一個合數K至少有一個小於等於的因數,因此我們用線性篩篩出的所有質數,將中所有該質數的倍數全部除去,最後再進行一邊掃描,找題目的要求就可以了。這裏因爲和比較大,我們可以映射到一個區域,來保證數組可以開下。
code:
#include <bits/stdc++.h>
using namespace std;
int read(){//快讀
int s=0,w=0;
char ch=getchar();
for(;ch<'0'||ch>'9';ch=getchar())s|=ch=='-';
for(;ch>='0'&&ch<='9';ch=getchar())w=(w<<3)+(w<<1)+(ch^48);
return s?-w:w;
}
int L,R;
int vis[65537],pr[15001],tot,issp[1000001];
//vis數組表示一個數是否爲質數
//pr數組則是記錄具體的質數是哪些
//issp數組表示的是每次L和R區間哪些數是質數
void Prime(){
//篩法,此處使用了歐拉篩法
vis[1]=1;
for(int i=2;i<=65536;++i){
if(!vis[i]){
pr[++tot]=i;
}
for(int j=1;j<=tot;++j){
if(i*pr[j]>65536){
break;
}
vis[i*pr[j]]=1;
if(!i%pr[j]){
break;
}
}
}
return;
}
int shift(int l,int r,int prime){
//該函數用來計算一個質數的多少倍是第一個出現在L-R區間中的。
//返回的是它與L的距離(因爲L,R較大,所以我們爲了避免開大數組而採用了讓所有下標減去L的方法來縮小範圍)
long long x=((long long)l+(long long)prime-(long long)1)/(long long)prime;
long long y=x*prime-l+1;
return int(y);
}
int main(){
Prime();
int TT=0,Max,Maxi,Maxj,Min,Mini,Minj;
//設置TT是爲了方便每次issp數組的使用,因爲凉心出題人的存在而爲了節約時間。對於每次修改issp就改爲TT,查詢改爲是否是TT這也是競賽中爲了節約時間的常用方法。
//Max記錄兩個質數距離最大是多少,Min則記錄兩個質數距離最小是多少。
//Maxi,Maxj則爲這兩個質數是誰,Mini,Minj同理。
while(cin>>L){
++TT;
R=read();
if(L==1)issp[L]=TT;//emmm特判1
int lastpr=-1;
Max=-0x3f3f3f3f,Maxi=-1,Maxj=-1,Min=0x3f3f3f3f,Mini=-1,Minj=-1;
//這些是初始工作
for(int i=1;i<=tot;++i){
if(pr[i]*pr[i]>R){
break;
//質數是否出界
}
if(pr[i]<L){
for(int j=shift(L,R,pr[i]);j<=R-L+1;j+=pr[i])
issp[j]=TT;
//記錄是否爲質數,不是則爲TT
}
else{
for(int j=int((long long)pr[i]*2-(long long)L+1);j<=R-L+1;j+=pr[i])
issp[j]=TT;
//同理
}
//此處分類討論了,或許可以不討論。
}
//這邊是將非質數篩去。
for(int j=1;j<=R-L+1;++j){
if(issp[j]!=TT&&lastpr==-1){
lastpr=j;
//lastpr意爲上一個質數。
}
else if(issp[j]!=TT&&lastpr!=-1){
if(j-lastpr>Max){
Max=j-lastpr;
Maxi=lastpr+L-1;
Maxj=j+L-1;
}
//找最大距離。
if(j-lastpr<Min){
Min=j-lastpr;
Mini=lastpr+L-1;
Minj=j+L-1;
}
//找最小距離。
lastpr=j;
//修改上一個質數。
}
}
//尋找最大距離和最小距離的過程
if(Maxi!=-1&&Maxj!=-1){
printf("%d,%d are closest, %d,%d are most distant.\n",Mini,Minj,Maxi,Maxj);
}
else{
puts("There are no adjacent primes.");
}
//輸出即可。
}
return 0;
}
2.GCD(check here)
題目描述:給定整數N,求1<=x,y<=N且Gcd(x,y)爲素數的數對(x,y)有多少對。
範圍:
Solution:範圍香不香?所以你根本無法枚舉,當然部分分是可以有的。考慮一下2個數的,這等於一個質數。質數??誰可以做到?我們知道是有篩法可以完成肝爆的,是不是意爲這我們可以將它往素數那一方面想呢?再考慮以下:設,那麼是等於多少的呢?那就是了。?那麼:假設y已經固定,那麼對於這個區間中,這樣的x有多少呢?無腦思考便可以得出結論:個。so?對於每個小於n的質數,計算的便是中互質的x,y。這樣的對有多少個呢?就是個!至此,本題得到了快速地解決。
code:
代碼先略。有它事在先。
3.青蛙的約會
題目描述:。。。
範圍:。。。
Solution:先將它給的銻式轉化。可以得到:那麼這個式子必然需要整治。所以我們開始魔改
這已經很像不定方程了!
再次改進,我們設n-m爲A,y-x爲-B,那原式變爲
這就可以使用擴歐解決。
但是請考慮一個問題,擴歐的式子:,所以我們所求的只是一個特解。
那麼所有解如何表示呢?
看:我們求得了一個,用這個式子減去最初的式子可以得到:
設兩邊同除,這樣可以使得新的互質,就可以得知:是整除的。所以我們便可以任意的去添加k而不會使得該等式不成立。所以最小的x0就是當x0與k互質時(即x0中不含k),那麼便可得知方程的最小解。但是上面的式子右邊是,設,則結果需要乘上。
code:
#include <ios>
#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <queue>
#include <stack>
#include <bitset>
#include <cctype>
#include <cerrno>
#include <cstdio>
#include <cwchar>
#include <fenv.h>
#include <iosfwd>
#include <limits>
#include <string>
#include <vector>
#include <clocale>
#include <complex>
#include <cstdlib>
#include <cstring>
#include <cwctype>
#include <fstream>
#include <iomanip>
#include <istream>
#include <ostream>
#include <sstream>
#include <utility>
#include <iostream>
#include <stdint.h>
#include <tgmath.h>
#include <algorithm>
#include <complex.h>
#include <exception>
#include <stdbool.h>
#include <stdexcept>
#include <streambuf>
#include <functional>
#include <inttypes.h>
using namespace std;
#define fi first
#define se second
#define ST struct
#define RE return
#define DT cout<<1
#define fro front()
#define ll long long
#define II inline int
#define enter puts("")
#define gc() getchar()
#define pob pop_back()
#define IB inline bool
#define IV inline void
#define entk printf(" ")
#define ID inline double
#define pii pair<int,int>
#define uint unsigned int
#define pub(x) push_back(x)
#define IL inline long long
#define psi pair<string,int>
#define pis pari<int,string>
#define mp(x,y) make_pair(x,y)
#define ull unsigned long long
#define pt1(a) printf("%d\n",a)
#define repi(x,a,b) for(x=a;x<=b;++x)
#define mes(x,y) memset(x,y,sizeof(x))
#define pt2(a,b) printf("%d %d\n",a,b)
#define rep(x,a,b) for(int x=a;x<=b;++x)
#define drep(x,a,b) for(int x=a;x>=b;--x)
#define pt3(a,b,c) printf("%d %d %d\n",a,b,c)
#define repe(i,x,a,e) for(int i=a[x];i;i=e[i].nxt)
#define pt4(a,b,c,d) printf("%d %d %d %d\n",a,b,c,d)
#define pt5(a,b,c,d,e) printf("%d %d %d %d %d\n",a,b,c,d,e)
#define pt6(a,b,c,d,e,f) printf("%d %d %d %d %d %d\n",a,b,c,d,e,f)
#define pt7(a,b,c,d,e,f,g) printf("%d %d %d %d %d %d %d\n",a,b,c,d,e,f,g)
#define fre(x) freopen(#x".in", "r", stdin),freopen(#x".out", "w", stdout)
#define pt8(a,b,c,d,e,f,g,h) printf("%d %d %d %d %d %d %d %d\n",a,b,c,d,e,f,g,h)
#define square(i,j,a,n,b,m,s) for(int i=a;i<=n;++i){for(int j=b;j<=m;++j)printf("%d ",s[i][j]);puts("");}
II sqri(int x){return x*x;}
IL sqrl(int x){return (ll)x*(ll)x;}
IL sqrll(ll x){return x*x;}
II readi(){
int s=0,w=0;
char ch=getchar();
for(;ch<'0'||ch>'9';ch=getchar())s|=ch=='-';
for(;ch>='0'&&ch<='9';ch=getchar())w=(w<<3)+(w<<1)+(ch^48);
return s?-w:w;
}
IL readl(){
int s=0;
ll w=0;
char ch=getchar();
for(;ch<'0'||ch>'9';ch=getchar())s|=ch=='-';
for(;ch>='0'&&ch<='9';ch=getchar())w=(w<<3)+(w<<1)+(ll)(ch^48);
return s?-w:w;
}
ll n,m,x,y,l,s,X1,Y1;
IL exgcd(ll a,ll b,ll &X1,ll &Y1){
if(!b){
X1=1;
Y1=0;
return a;
}
s=exgcd(b,a%b,X1,Y1);
ll New=X1;
X1=Y1;
Y1=New-a/b*Y1;
return s;
}
int main(){
fre(1);
x=readl(),y=readl(),m=readl(),n=readl(),l=readl();
y=x-y,x=n-m;
if(x<0)x=-x,y=-y;
exgcd(x,l,X1,Y1);
if(y%s)puts("Impossible");
else cout<<((X1*(y/s))%(l/s)+(l/s))%(l/s);
RE 0;
}