題解 P5285 【[十二省聯考2019]騙分過樣例】
阿新 • • 發佈:2020-10-04
題目:
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;
}