1. 程式人生 > 實用技巧 >題解 P5285 【[十二省聯考2019]騙分過樣例】

題解 P5285 【[十二省聯考2019]騙分過樣例】

題目:

點此檢視題目

Case 1~3

看這裡的功能編號,不難猜出998244353是模數,再看一下資料點:

輸入:0,1,2,3……

輸出:1,19,361,6859……

發現都是求19的n次冪,於是我們可以用快速冪

不過第三個點的數很大,於是我們用尤拉定理,邊讀入邊向998244353-1取模

程式碼:

I LL mul(LL a,LL b,LL p){a%=p;b%=p;long long c=(long double)a*b/p;long long ans=a*b-c*p;if(ans<0) ans+=p;else if(ans>=p) ans-=p;return ans;}//快速乘
I LL mi(LL x,LL p,LL m){LL r=1;while(p){if(p&1LL)r=mul(r,x,m);p>>=1;x=mul(x,x,m);}return r;}//快速冪
I LL readd(LL X){LL f=1,x=0;char ch=getchar();while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}while(isdigit(ch))x=((x<<3)+(x<<1)+(ch^48))%X,ch=getchar();return x*f;}
class ks{
	public:
		void sor(LL m){//m是模數
			LL n=read();
			for(LL i=1,q;i<=n;i++){
				q=readd(m-1);
				write(mi(19,q,m));
				putchar('\n');
			}
		}
}we;

Case 4

一看,嗯?放模數的位數變成了什麼,考慮到資料範圍不大,我們可以列舉求數,得到模數為1145141

於是,把之前的模板改成

we.sor(1145141);

就好了

Case 5

1?+。。。一看就是1?的升級版。

模數太大,不能枚舉了,於是我們考慮計算,結果為5211500658258874318,然後照樣套板子

we.sor(5211500658258874318);

Case 6~7

這回,功能編號裡出來了一個wa?經過資料分析,不難猜到是打

x=x*19%m

時爆int了,於是我們去找他的迴圈節,最終找到在第55245個數的時候,每過45699個數重複一次

於是,就可以打出這部分的程式碼了

class waks{
	private:
		#define X 55244//開始位置
		#define Y 45699//迴圈週期
		int a[X+Y+10];
		LL n,i,x;
	public:
		I void sor(){
			for(a[0]=i=1;i<=X+Y;i++){
				a[i]=19*a[i-1]%998244353;
			}
			n=read();
			while(n--){
				x=read();
				write(a[x<=X?x:(x-X)%Y+X]);
				putchar('\n');
			}
		}
}wawe;

Case 8~10

首先,研究資料可得,p為Prime(素數),然後題目要求就是對一段區間內質數輸出p,合數輸出.。

判斷素數我們可以用MilleRabin,於是就可以打出這部分的程式碼了

void ini(int n){//質數篩
	ck[1]=1;
	for(int i=2;i<=n;i++){
		if(!ck[i]) pr[++tot]=i;
		for(int j=1;j<=tot;j++){
			if(i*pr[j]>n) break;
			ck[i*pr[j]]=1;
			if(i%pr[j]==0) break;
		}
	}
}
class MillerRabin{//判斷質數
	public:
		bool M_R(LL x,int t){
			if(x<=4e6) return !ck[x];
			for(int i=1;i<=30;i++) if(x%pr[i]==0) return 0;
			for(int i=1;i<=t;i++){
				LL y=pr[i];
				if(mi(y,x-1,x)!=1) return 0;
				LL v=x-1,t=1;
				while(t==1 && ~v&1){
					t=mi(y,v>>=1,x);
					if(t!=1&&t!=x-1) return 0;
				}
			}return 1;
		}
}MR;
class _2p{
	private:
		LL l,r,n;
	public:
		I void prime(){
			n=read();
			W(n--){
				l=read();r=read();
				for(LL i=l;i<=r;i++){
					putchar(MR.M_R(i,5)?'p':'.');
				}
				putchar('\n');
			}
		}
}Pr;

Case 11~13

看到u,以及輸出為0,+,-,便不難想到是求莫比烏斯函式μ。

我們可以直接用線性篩

程式碼如下:

class mbws{
	private:
		int n,t;LL l,r,x,L,R,p;
		int wer[10001000];LL ab[10001000];
		char tra(int x){return x==0?'0':(x>0?'+':'-');}
	public:
		void sor(){
			n=read();
			while(n--){
				l=read();r=read();
				for(LL j=1;j<=r-l+1;j++) wer[j]=1,ab[j]=j+l-1;
				for(LL j=1;j<=tot;j++){
					x=pr[j];
					for(LL p=x*((l-1)/x+1)-l+1;p<=r-l+1;p+=x){
						if(ab[p]%(x*x)==0) wer[p]=0;
						else wer[p]=-wer[p],ab[p]/=x;
					}
				}
				for(LL j=1;j<=r-l+1;j++){
					x=ab[j];
					if(wer[j]&&x>1){
						LL y=sqrt(x);
						if(y*y==x) wer[j]=0;
						else if(x<=1e14||MR.M_R(x,1))wer[j]=-wer[j];
					}
					if(wer[j]) putchar(~wer[j]?'+':'-');
					else putchar('0');
				}
				putchar('\n');
			}
		}
}U;

Case 14~16

g=原根,這就相當於要我們求一段區間內每個數是否為給定質數的原根。

發現這個點的模數全為998244353,對此直接暴力分解998244352,然後暴力判斷即可:

通過計算,Case 16的模數為1515343657,於是,就可以寫出這一部分的程式碼

class yuangeng{
	private:
		int MO;
		int p[20],cnt;
		int vis[15000000],id[15000000];
		I void fact(int x) {
			cnt=0;
			for (RI i=2;i*i<=x;++i) {
				if (x%i) continue;
				p[++cnt]=i;
				while (x%i==0) x/=i;
			}
			if (x>1) p[++cnt]=x;
		}
		I int check(int x) {
			for(RI i=1;i<=cnt;++i)
				if (mi(x,(MO-1)/p[i],MO)==1) return 0;
			return 1;
		}
		I int getg(){
			for (RI i=2;;++i)
				if (check(i)) return i;
		}
	public:
		I void sor() {
			int T=read();
			while (T--) {
				int l=read(),r=read();
				if (r==234133333) MO=1515343657;
				else MO=read();
				fact(MO-1);
				if (r-l<=1e6) {
					for (RI i=l;i<=r;++i) putchar(".g"[check(i)]);
					putchar('\n');
				} else {
					memset(vis,0,sizeof(vis));
					for (RI i=1;i<=cnt;++i)
						for (RI j=p[i];j<MO;j+=p[i])
							vis[j]=1;
					int g=getg();
					for (RI i=1,pw=g;i<MO;++i,pw=1ll*pw*g%MO) id[pw]=i;
					for (RI i=l;i<=r;++i) putchar("g."[vis[id[i]]]);
					putchar('\n');
				}
			}
		}
}G;

程式碼:

放一下最終程式碼

#include<bits/stdc++.h>
using namespace std;
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define RL Reg LL
#define RU Reg ull
#define Con const
#define CI Con int&
#define CL Con LL&
#define CU Con ull&
#define I inline
#define W while
#define LL long long
#define ULL unsigned long long
#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)<(y)?(x):(y))
#define Gmax(x,y) (x<(y)&&(x=(y)))
#define Gmin(x,y) (x>(y)&&(x=(y)))
int tot,pr[10001000];
bool ck[10001000];
I LL mul(LL a,LL b,LL p){a%=p;b%=p;long long c=(long double)a*b/p;long long ans=a*b-c*p;if(ans<0) ans+=p;else if(ans>=p) ans-=p;return ans;}
I LL mi(LL x,LL p,LL m){LL r=1;while(p){if(p&1LL)r=mul(r,x,m);p>>=1;x=mul(x,x,m);}return r;}
I LL read(){LL f=1,x=0;char ch=getchar();while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}while(isdigit(ch))x=(x<<3)+(x<<1)+(ch^48),ch=getchar();return x*f;}
I LL readd(LL X){LL f=1,x=0;char ch=getchar();while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}while(isdigit(ch))x=((x<<3)+(x<<1)+(ch^48))%X,ch=getchar();return x*f;}
void write(LL x){if(x<0)putchar('-'),x=-x;if(x>9)write(x/10);putchar((x-x/10*10)+'0');}
void ini(int n){
	ck[1]=1;
	for(int i=2;i<=n;i++){
		if(!ck[i]) pr[++tot]=i;
		for(int j=1;j<=tot;j++){
			if(i*pr[j]>n) break;
			ck[i*pr[j]]=1;
			if(i%pr[j]==0) break;
		}
	}
}
class ks{
	public:
		void sor(LL m){
			LL n=read();
			for(LL i=1,q;i<=n;i++){
				q=readd(m-1);
				write(mi(19,q,m));
				putchar('\n');
			}
		}
}we;
class waks{
	private:
		#define X 55244
		#define Y 45699
		int a[X+Y+10];
		LL n,i,x;
	public:
		I void sor(){
			for(a[0]=i=1;i<=X+Y;i++){
				a[i]=19*a[i-1]%998244353;
			}
			n=read();
			while(n--){
				x=read();
				write(a[x<=X?x:(x-X)%Y+X]);
				putchar('\n');
			}
		}
}wawe;
class MillerRabin{
	public:
		bool M_R(LL x,int t){
			if(x<=4e6) return !ck[x];
			for(int i=1;i<=30;i++) if(x%pr[i]==0) return 0;
			for(int i=1;i<=t;i++){
				LL y=pr[i];
				if(mi(y,x-1,x)!=1) return 0;
				LL v=x-1,t=1;
				while(t==1 && ~v&1){
					t=mi(y,v>>=1,x);
					if(t!=1&&t!=x-1) return 0;
				}
			}return 1;
		}
}MR;
class _2p{
	private:
		LL l,r,n;
	public:
		I void prime(){
			n=read();
			W(n--){
				l=read();r=read();
				for(LL i=l;i<=r;i++){
					putchar(MR.M_R(i,5)?'p':'.');
				}
				putchar('\n');
			}
		}
}Pr;
class mbws{
	private:
		int n,t;LL l,r,x,L,R,p;
		int wer[10001000];LL ab[10001000];
		char tra(int x){return x==0?'0':(x>0?'+':'-');}
	public:
		void sor(){
			n=read();
			while(n--){
				l=read();r=read();
				for(LL j=1;j<=r-l+1;j++) wer[j]=1,ab[j]=j+l-1;
				for(LL j=1;j<=tot;j++){
					x=pr[j];
					for(LL p=x*((l-1)/x+1)-l+1;p<=r-l+1;p+=x){
						if(ab[p]%(x*x)==0) wer[p]=0;
						else wer[p]=-wer[p],ab[p]/=x;
					}
				}
				for(LL j=1;j<=r-l+1;j++){
					x=ab[j];
					if(wer[j]&&x>1){
						LL y=sqrt(x);
						if(y*y==x) wer[j]=0;
						else if(x<=1e14||MR.M_R(x,1))wer[j]=-wer[j];
					}
					if(wer[j]) putchar(~wer[j]?'+':'-');
					else putchar('0');
				}
				putchar('\n');
			}
		}
}U;
class yuangeng{
	private:
		int MO;
		int p[20],cnt;
		int vis[15000000],id[15000000];
		I void fact(int x) {
			cnt=0;
			for (RI i=2;i*i<=x;++i) {
				if (x%i) continue;
				p[++cnt]=i;
				while (x%i==0) x/=i;
			}
			if (x>1) p[++cnt]=x;
		}
		I int check(int x) {
			for(RI i=1;i<=cnt;++i)
				if (mi(x,(MO-1)/p[i],MO)==1) return 0;
			return 1;
		}
		I int getg(){
			for (RI i=2;;++i)
				if (check(i)) return i;
		}
	public:
		I void sor() {
			int T=read();
			while (T--) {
				int l=read(),r=read();
				if (r==234133333) MO=1515343657;
				else MO=read();
				fact(MO-1);
				if (r-l<=1e6) {
					for (RI i=l;i<=r;++i) putchar(".g"[check(i)]);
					putchar('\n');
				} else {
					memset(vis,0,sizeof(vis));
					for (RI i=1;i<=cnt;++i)
						for (RI j=p[i];j<MO;j+=p[i])
							vis[j]=1;
					int g=getg();
					for (RI i=1,pw=g;i<MO;++i,pw=1ll*pw*g%MO) id[pw]=i;
					for (RI i=l;i<=r;++i) putchar("g."[vis[id[i]]]);
					putchar('\n');
				}
			}
		}
}G;
int main(){

	string s;
	getline(cin,s);
	ini(10000000);
	if(s=="1_998244353")we.sor(998244353);
	if(s=="1?")we.sor(1145141);
	if(s=="1?+")we.sor(5211600617818708273);
	if(s=="1wa_998244353")wawe.sor();
	if(s=="2p")Pr.prime();
	if(s=="2u")U.sor();
	if(s=="2g")G.sor();
	if(s=="2g?")G.sor();

	return 0;
}