數論

今天是來講數論的

(by 銻’s口胡,大佬輕拍)

1.Prime Distance(check here

題目描述:給你一個L,一個R,求L-R中最近的兩個質數以及最遠的兩個質數。
範圍:1L,R2147483647RL<=1061\le L,R \le2147483647,R-L<=10^6
Solution:首先對於LRL,R,非常的大,已知的所有篩法都無法在規定時間內求解。但是可以看到範圍裏還有很鬼畜的一條東西:RL<=106R-L<=10^6。根據它我們可以看出來,我們是可以掃一遍LRL-R的,考慮到一個合數K至少有一個小於等於K\sqrt{K}的因數,因此我們用線性篩篩出R\sqrt{R}的所有質數,將LRL-R中所有該質數的倍數全部除去,最後再進行一邊掃描,找題目的要求就可以了。這裏因爲LLRR比較大,我們可以映射到一個區域,來保證數組可以開下。

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)有多少對。
範圍:1n1071\le n\le10^7
Solution:範圍香不香?所以你根本無法枚舉,當然部分分是可以有的。考慮一下2個數的gcd(x,y)gcd(x,y),這等於一個質數。質數?10710^7?誰可以做到?我們知道是有篩法可以完成1s1s肝爆10710^7的,是不是意爲這我們可以將它往素數那一方面想呢?再考慮以下:設gcd(x,y)=zgcd(x,y)=z,那麼gcd(x/z,y/z)gcd(x/z,y/z)是等於多少的呢?那就是11了。11?那麼:假設y已經固定,那麼對於1y1-y這個區間中,這樣的x有多少呢?無腦思考便可以得出結論:φ(n)φ(n)個。so?對於每個小於n的質數,計算的便是1x,ynp1\le x,y\le \frac np中互質的x,y。這樣的對有多少個呢?就是φ(np)2φ(\frac np)*2個!至此,本題得到了快速地解決。

code:

代碼先略。有它事在先。

3.青蛙的約會

題目描述:。。。
範圍:。。。
Solution:先將它給的銻式轉化。可以得到:x+kmy+kn(modl)x+km≡y+kn\pmod l那麼這個式子必然需要整治。所以我們開始魔改

x+kmy+kn(modl)xy+k(mn)0(modl)x+km≡y+kn\pmod l →x-y+k(m-n)≡0\pmod l →
k(mn)al=yxk(m-n)-a*l=y-x
這已經很像不定方程了!
再次改進,我們設n-m爲A,y-x爲-B,那原式變爲kA+al=Bk*A+a*l=B
這就可以使用擴歐解決。
但是請考慮一個問題,擴歐的式子:ax+by=gcd(a,b)a*x+b*y=gcd(a,b),所以我們所求的只是一個特解。
那麼所有解如何表示呢?
看:我們求得了一個ax0+by0=ca*x0+b*y0=c,用這個式子減去最初的式子可以得到:a(xx0)+b(yy0)=0a*(x-x0)+b*(y-y0)=0
k=gcd(a,b)k=gcd(a,b)兩邊同除kk,這樣可以使得新的aba,b互質,就可以得知:bk\frac bk是整除xx0x-x0的。所以我們便可以任意的去添加k而不會使得該等式不成立。所以最小的x0就是當x0與k互質時(即x0中不含k),那麼便可得知方程的最小解。但是上面的式子右邊是gcd(a,b)gcd(a,b),設S=gcd(a,b)S=gcd(a,b),則結果需要乘上bS\frac bS

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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章