【洛谷5246】[集训队互测2016] 消失的源代码(有趣的提答题)
大致题意: 共\(10\)个\(Subtask\),每个\(Subtask\)给你一个不完美的可执行程序和一个输入文件,让你求出输出文件。
子任务\(1\)
简单分析,可以发现对于每个输入的字符,你要输出一个与其对应的字符。
则可通过打表得到每个字符所对应的字符。
代码如下:
#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
using namespace std;
int v[27]={0,'y','f','r','b','k','g','i','m','u','j','v','p','h','a','t','d','s','n','e','l','o','z','c','x','w','q'};//打得的表
class FastIO
{
private:
#define FS 100000
#define tc() (A==B&&(B=(A=FI)+fread(FI,1,FS,stdin),A==B)?EOF:*A++)
#define tn(x) (x<<3)+(x<<1)
#define D isdigit(c=tc())
char c,*A,*B,FI[FS];
public:
I FastIO() {A=B=FI;}
Tp I void read(Ty& x) {x=0;W(!D);W(x=tn(x)+(c&15),D);}
Ts I void read(Ty& x,Ar&... y) {read(x),read(y...);}
I void reads(string& x) {x="";W(isspace(c=tc()));W(x+=c,!isspace(c=tc())&&~c);}
}F;
int main()
{
freopen("input1.txt","r",stdin),freopen("output1.txt","w",stdout);
RI Tpos,Ttot,i,len;Reg char c;Reg string s;
F.read(Tpos,Ttot);W(Ttot--)
{
for(F.reads(s),len=s.length(),i=0;i^len;++i) putchar(v[s[i]&31]);//输出对应字符
putchar('\n');//换行
}return 0;
}
子任务\(2\)
先打表得到\(n=1\sim5\)的输出结果分别为\(2030,8082,18166,32282,50430\)。
考虑其每次增加的值分别为\(6052,10084,14116,18148\),而增加的值所相差的值都为\(4032\)!
设第\(i\)个数为\(f_i\),则不难得到:
貌似做完了?
等等,这种式子肯定需要取模!
我们继续打表,可以发现在\(n=10\)时,\(ans=201650\),但\(n=11\)时,\(ans\)就变成了\(10657\)。
而\(f_{11}=243990\),与\(10657\)刚好相差\(233333\)。
所以模数必为\(233333\)。
代码如下:
#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define X 233333
using namespace std;
class FastIO
{
private:
#define FS 100000
#define tc() (A==B&&(B=(A=FI)+fread(FI,1,FS,stdin),A==B)?EOF:*A++)
#define pc(c) (C^FS?FO[C++]=c:(fwrite(FO,1,C,stdout),FO[(C=0)++]=c))
#define tn(x) (x<<3)+(x<<1)
#define D isdigit(c=tc())
int T,C;char c,*A,*B,FI[FS],FO[FS],S[FS];
public:
I FastIO() {A=B=FI;}
Tp I void read(Ty& x) {x=0;W(!D);W(x=tn(x)+(c&15),D);}
Ts I void read(Ty& x,Ar&... y) {read(x),read(y...);}
Tp I void write(Ty x) {W(S[++T]=x%10+48,x/=10);W(T) pc(S[T--]);}
Tp I void writeln(Con Ty& x) {write(x),pc('\n');}
I void clear() {fwrite(FO,1,C,stdout),C=0;}
}F;
int main()
{
freopen("input2.txt","r",stdin),freopen("output2.txt","w",stdout);
RI Tpos,Ttot,x;F.read(Tpos,Ttot);W(Ttot--) F.read(x),F.writeln((1LL*2016*x%X*x%X+4LL*x+10)%X);//计算并输出答案
return F.clear(),0;
}
子任务\(3\)
同样是考虑打表,发现这次得到的式子增长速度特别慢。
与\(hl666\)神仙一起想了半天没想出来,最后放到\(OEIS\)上,发现是这样一个式子:
代码如下:
#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
using namespace std;
const double Pi=acos(-1);
class FastIO
{
private:
#define FS 100000
#define tc() (A==B&&(B=(A=FI)+fread(FI,1,FS,stdin),A==B)?EOF:*A++)
#define pc(c) (C^FS?FO[C++]=c:(fwrite(FO,1,C,stdout),FO[(C=0)++]=c))
#define tn(x) (x<<3)+(x<<1)
#define D isdigit(c=tc())
int T,C;char c,*A,*B,FI[FS],FO[FS],S[FS];
public:
I FastIO() {A=B=FI;}
Tp I void read(Ty& x) {x=0;W(!D);W(x=tn(x)+(c&15),D);}
Ts I void read(Ty& x,Ar&... y) {read(x),read(y...);}
Tp I void write(Ty x) {W(S[++T]=x%10+48,x/=10);W(T) pc(S[T--]);}
Tp I void writeln(Con Ty& x) {write(x),pc('\n');}
I void clear() {fwrite(FO,1,C,stdout),C=0;}
}F;
int main()
{
freopen("input3.txt","r",stdin),freopen("output3.txt","w",stdout);
RI Tpos,Ttot,x;F.read(Tpos,Ttot);W(Ttot--) F.read(x),F.writeln((int)floor(sqrt(x/Pi)));//计算并输出答案
return F.clear(),0;
}
子任务\(4\)
观察数据形式,易得:输入第一行两个数数\(n,m\),分别表示节点个数和边数。其后\(m\)行,每行两个数表示一条边。
观察样例,可发现答案就是各连通块大小的平方和。
可以用并查集维护连通性,最后再统计答案即可。
代码如下:
#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define N 100000
#define LL long long
using namespace std;
int n,m;
class FastIO
{
private:
#define FS 100000
#define tc() (A==B&&(B=(A=FI)+fread(FI,1,FS,stdin),A==B)?EOF:*A++)
#define pc(c) (C^FS?FO[C++]=c:(fwrite(FO,1,C,stdout),FO[(C=0)++]=c))
#define tn(x) (x<<3)+(x<<1)
#define D isdigit(c=tc())
int T,C;char c,*A,*B,FI[FS],FO[FS],S[FS];
public:
I FastIO() {A=B=FI;}
Tp I void read(Ty& x) {x=0;W(!D);W(x=tn(x)+(c&15),D);}
Ts I void read(Ty& x,Ar&... y) {read(x),read(y...);}
Tp I void write(Ty x) {W(S[++T]=x%10+48,x/=10);W(T) pc(S[T--]);}
Tp I void writeln(Con Ty& x) {write(x),pc('\n');}
I void clear() {fwrite(FO,1,C,stdout),C=0;}
}F;
class UnionFindSet//并查集
{
private:
static const int SZ=N;int fa[SZ+5],cnt[SZ+5];
I int getfa(CI x) {return fa[x]^x?fa[x]=getfa(fa[x]):x;}//找祖先
public:
I void Init(CI n) {for(RI i=1;i<=n;++i) cnt[fa[i]=i]=0;}//初始化
I void Union(RI x,RI y) {(x=getfa(x))^(y=getfa(y))&&(fa[y]=x);}//合并两个节点
I LL Query(CI n)//询问
{
RI i;Reg LL ans=0;for(i=1;i<=n;++i) ++cnt[getfa(i)];//统计
for(i=1;i<=n;++i) ans+=1LL*cnt[i]*cnt[i];return ans;//计算答案
}
}U;
int main()
{
freopen("input4.txt","r",stdin),freopen("output4.txt","w",stdout);
RI Tpos,Ttot,i,x,y;F.read(Tpos,Ttot);W(Ttot--)
{
for(F.read(n,m),U.Init(n),i=1;i<=m;++i) F.read(x,y),U.Union(x,y);//对每条边依次合并连通块
F.writeln(U.Query(n));//输出答案
}return F.clear(),0;
}
子任务\(5\)
观察数据形式,易得:输入第一行两个数\(n,Q\),分别表示节点个数和询问个数。其后\(n-1\)行,每行两个数表示一条边(可见这是一棵树)。再然后是\(Q\)行,每行两个数,表示一个询问。
手造小数据容易得出,每次询问的是树上两点间的距离,最后要输出答案的异或和。
这用树上倍增即可。
代码如下:
#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define N 100000
#define LogN 17
#define LL long long
#define swap(x,y) (x^=y^=x^=y)
#define add(x,y,v) (e[++ee].nxt=lnk[x],e[lnk[x]=ee].to=y,e[ee].val=v)
using namespace std;
int n,m,ee,lnk[N+5];struct edge {int to,nxt,val;}e[N<<1];
class FastIO
{
private:
#define FS 100000
#define tc() (A==B&&(B=(A=FI)+fread(FI,1,FS,stdin),A==B)?EOF:*A++)
#define pc(c) (C^FS?FO[C++]=c:(fwrite(FO,1,C,stdout),FO[(C=0)++]=c))
#define tn(x) (x<<3)+(x<<1)
#define D isdigit(c=tc())
int T,C;char c,*A,*B,FI[FS],FO[FS],S[FS];
public:
I FastIO() {A=B=FI;}
Tp I void read(Ty& x) {x=0;W(!D);W(x=tn(x)+(c&15),D);}
Ts I void read(Ty& x,Ar&... y) {read(x),read(y...);}
Tp I void write(Ty x) {W(S[++T]=x%10+48,x/=10);W(T) pc(S[T--]);}
Tp I void writeln(Con Ty& x) {write(x),pc('\n');}
I void clear() {fwrite(FO,1,C,stdout),C=0;}
#undef D
}F;
class TreeSolver//树上倍增
{
private:
int D[N+5],F[N+5][LogN+5];LL Dis[N+5][LogN+5];
public:
I void dfs(CI x,CI lst)//DFS预处理
{
RI i;for(i=1;i<=LogN;++i) F[x][i]=F[F[x][i-1]][i-1],Dis[x][i]=Dis[x][i-1]+Dis[F[x][i-1]][i-1];//求出F数组和Dis数组
for(i=lnk[x];i;i=e[i].nxt) e[i].to^lst&&(D[e[i].to]=D[F[e[i].to][0]=x]+1,Dis[e[i].to][0]=e[i].val,dfs(e[i].to,x),0);//遍历子树
}
I LL GetDis(RI x,RI y)//求出树上两点间的距离
{
RI i;Reg LL t=0;for(D[x]<D[y]&&swap(x,y),i=0;D[x]^D[y];++i) (D[x]^D[y])&(1<<i)&&(t+=Dis[x][i],x=F[x][i]);
if(!(x^y)) return t;for(i=LogN;~i;--i) F[x][i]^F[y][i]&&(t+=Dis[x][i]+Dis[y][i],x=F[x][i],y=F[y][i]);
return t+Dis[x][0]+Dis[y][0];
}
}T;
int main()
{
freopen("input5.txt","r",stdin),freopen("output5.txt","w",stdout);
RI Tpos,Ttot,i,x,y,v;Reg LL ans;F.read(Tpos,Ttot);W(Ttot--)
{
for(F.read(n,m),ee=0,i=1;i<=n;++i) lnk[i]=0;for(i=1;i^n;++i) F.read(x,y,v),add(x,y,v),add(y,x,v);//清空数组+读入+连边
for(T.dfs(1,0),ans=0,i=1;i<=m;++i) F.read(x,y),ans^=T.GetDis(x,y);F.writeln(ans);//求解答案
}return F.clear(),0;
}
子任务\(6\)
与子任务\(5\)差不多,只不过询问的变成了树上两点间的最小边权。
我们可以通过询问同一个点间的最小边权,来求出其\(ans\)初始化为\(1987654321\)。
然后同样用树上倍增即可。
代码如下:
#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define N 100000
#define LogN 17
#define min(x,y) ((x)<(y)?(x):(y))
#define Gmin(x,y) ((x)>(y)&&(x=(y)))
#define swap(x,y) (x^=y^=x^=y)
#define add(x,y,v) (e[++ee].nxt=lnk[x],e[lnk[x]=ee].to=y,e[ee].val=v)
using namespace std;
int n,m,ee,lnk[N+5];struct edge {int to,nxt,val;}e[N<<1];
class FastIO
{
private:
#define FS 100000
#define tc() (A==B&&(B=(A=FI)+fread(FI,1,FS,stdin),A==B)?EOF:*A++)
#define pc(c) (C^FS?FO[C++]=c:(fwrite(FO,1,C,stdout),FO[(C=0)++]=c))
#define tn(x) (x<<3)+(x<<1)
#define D isdigit(c=tc())
int T,C;char c,*A,*B,FI[FS],FO[FS],S[FS];
public:
I FastIO() {A=B=FI;}
Tp I void read(Ty& x) {x=0;W(!D);W(x=tn(x)+(c&15),D);}
Ts I void read(Ty& x,Ar&... y) {read(x),read(y...);}
Tp I void write(Ty x) {W(S[++T]=x%10+48,x/=10);W(T) pc(S[T--]);}
Tp I void writeln(Con Ty& x) {write(x),pc('\n');}
I void clear() {fwrite(FO,1,C,stdout),C=0;}
#undef D
}F;
class TreeSolver//树上倍增
{
private:
#define P 1987654321//ans初始值
int D[N+5],F[N+5][LogN+5],M[N+5][LogN+5];
public:
I void dfs(CI x,CI lst)//DFS预处理
{
RI i;for(i=1;i<=LogN;++i) F[x][i]=F[F[x][i-1]][i-1],M[x][i]=min(M[x][i-1],M[F[x][i-1]][i-1]);//求出F数组和M数组
for(i=lnk[x];i;i=e[i].nxt) e[i].to^lst&&(D[e[i].to]=D[F[e[i].to][0]=x]+1,M[e[i].to][0]=e[i].val,dfs(e[i].to,x),0);//遍历子树
}
I int GetMin(RI x,RI y)//求出树上两点间的最小边权
{
RI i,t=P;for(D[x]<D[y]&&swap(x,y),i=0;D[x]^D[y];++i) (D[x]^D[y])&(1<<i)&&(Gmin(t,M[x][i]),x=F[x][i]);
if(!(x^y)) return t;for(i=LogN;~i;--i) F[x][i]^F[y][i]&&(Gmin(t,M[x][i]),Gmin(t,M[y][i]),x=F[x][i],y=F[y][i]);
return min(t,min(M[x][0],M[y][0]));
}
}T;
int main()
{
freopen("input6.txt","r",stdin),freopen("output6.txt","w",stdout);
RI Tpos,Ttot,i,x,y,v,ans;F.read(Tpos,Ttot);W(Ttot--)
{
for(F.read(n,m),ee=0,i=1;i<=n;++i) lnk[i]=0;for(i=1;i^n;++i) F.read(x,y,v),add(x,y,v),add(y,x,v);//清空数组+读入+连边
for(T.dfs(1,0),ans=0,i=1;i<=m;++i) F.read(x,y),ans^=T.GetMin(x,y);F.writeln(ans);//求解答案
}return F.clear(),0;
}
子任务\(7\)
数据给你的是两个数\(n\)和\(m\)。
通过大量测试和猜测可得我们要求的式子为:
观察\(input.txt\),可以发现除了一组\(100\ 1000\)的数据外,其余的数据都满足\(n=m\)。
而\(100\ 1000\)的数据我们完全可以暴力求解。
否则,我们将\(n=m\)代入得到:
这应该是比较经典的式子,我们枚举\(gcd\)得:
将\(d\)提前得:
而后半部分可以运用\(\phi\)的定义转化,于是得到这样一个式子:
\(n\)不大,可以直接线性筛筛出\(\phi\)的前缀和,然后枚举\(d\)求解即可。
代码如下:
#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define LL long long
using namespace std;
int n,m;
class FastIO
{
private:
#define FS 100000
#define tc() (A==B&&(B=(A=FI)+fread(FI,1,FS,stdin),A==B)?EOF:*A++)
#define pc(c) (C^FS?FO[C++]=c:(fwrite(FO,1,C,stdout),FO[(C=0)++]=c))
#define tn(x) (x<<3)+(x<<1)
#define D isdigit(c=tc())
int T,C;char c,*A,*B,FI[FS],FO[FS],S[FS];
public:
I FastIO() {A=B=FI;}
Tp I void read(Ty& x) {x=0;W(!D);W(x=tn(x)+(c&15),D);}
Ts I void read(Ty& x,Ar&... y) {read(x),read(y...);}
Tp I void write(Ty x) {W(S[++T]=x%10+48,x/=10);W(T) pc(S[T--]);}
Tp I void writeln(Con Ty& x) {write(x),pc('\n');}
I void clear() {fwrite(FO,1,C,stdout),C=0;}
}F;
class BruteForceSolver//暴力求解n!=m的情况
{
private:
I int gcd(CI x,CI y) {return y?gcd(y,x%y):x;}//求解gcd
public:
I void Solve()
{
RI i,j;Reg LL ans=0;
for(i=1;i<=n;++i) for(j=1;j<=m;++j) ans+=gcd(i,j);//大暴力统计答案
F.writeln(ans);//输出答案
}
}B;
class MathSolver//用数学方法求解n=m的情况
{
private:
class LineSiever//线性筛筛出φ的前缀和
{
private:
static const int SZ=1000000;int Pcnt,P[SZ+5],phi[SZ+5];
public:
LL Sphi[SZ+5];
I LineSiever()
{
RI i,j;for(phi[1]=1,i=2;i<=SZ;++i) for(!P[i]&&(phi[P[++Pcnt]=i]=i-1),j=1;1LL*i*P[j]<=SZ;++j)
if(P[i*P[j]]=1,i%P[j]) phi[i*P[j]]=phi[i]*(P[j]-1);else {phi[i*P[j]]=phi[i]*P[j];break;}
for(i=1;i<=SZ;++i) Sphi[i]=Sphi[i-1]+phi[i];//统计前缀和
}
}S;
public:
I void Solve()
{
RI i;Reg LL ans=0;
for(i=1;i<=n;++i) ans+=1LL*i*(2*S.Sphi[n/i]-1);//统计答案
F.writeln(ans);//输出答案
}
}M;
int main()
{
freopen("input7.txt","r",stdin),freopen("output7.txt","w",stdout);
RI Tpos,Ttot;F.read(Tpos,Ttot);W(Ttot--) F.read(n,m),n^m?B.Solve():M.Solve();//分情况选择解决方案
return F.clear(),0;
}
子任务\(8\)
手造几组小数据,可发现这题求的是给定序列本质不同的子串个数。
后缀数组裸题,答案就是:
代码如下:
#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define N 1000000
#define LL long long
using namespace std;
int n,a[N+5];
class FastIO
{
private:
#define FS 100000
#define tc() (A==B&&(B=(A=FI)+fread(FI,1,FS,stdin),A==B)?EOF:*A++)
#define pc(c) (C^FS?FO[C++]=c:(fwrite(FO,1,C,stdout),FO[(C=0)++]=c))
#define tn(x) (x<<3)+(x<<1)
#define D isdigit(c=tc())
int T,C;char c,*A,*B,FI[FS],FO[FS],S[FS];
public:
I FastIO() {A=B=FI;}
Tp I void read(Ty& x) {x=0;W(!D);W(x=tn(x)+(c&15),D);}
Ts I void read(Ty& x,Ar&... y) {read(x),read(y...);}
Tp I void write(Ty x) {W(S[++T]=x%10+48,x/=10);W(T) pc(S[T--]);}
Tp I void writeln(Con Ty& x) {write(x),pc('\n');}
I void clear() {fwrite(FO,1,C,stdout),C=0;}
}F;
class SuffixArray//后缀数组
{
private:
static const int SZ=N;int n,SA[SZ+5],H[SZ+5],R[SZ+5],P[SZ+5],T[SZ+5];
I void Rsort(CI S)//基数排序
{
RI i;for(i=0;i<=S;++i) T[i]=0;for(i=1;i<=n;++i) ++T[R[i]];
for(i=1;i<=S;++i) T[i]+=T[i-1];for(i=n;i;--i) SA[T[R[P[i]]]--]=P[i];
}
I void GetSA(int* s)//求出SA数组
{
RI i,k,S=N,t=0;for(i=1;i<=n;++i) R[P[i]=i]=s[i];
for(Rsort(S),k=1;t^n;k<<=1)
{
for(S=t,t=0,i=1;i<=k;++i) P[++t]=n-k+i;
for(i=1;i<=n;++i) SA[i]>k&&(P[++t]=SA[i]-k);
for(Rsort(S),i=1;i<=n;++i) P[i]=R[i];
for(R[SA[1]]=t=1,i=2;i<=n;++i) R[SA[i]]=(P[SA[i-1]]^P[SA[i]]||P[SA[i-1]+k]^P[SA[i]+k])?++t:t;
}
}
I void GetHeight(int* s)//求出Height数组
{
RI i,j,k=0;for(i=1;i<=n;++i) R[SA[i]]=i;
for(i=1;i<=n;++i)
{
if(k&&--k,!(R[i]^1)) continue;j=SA[R[i]-1];
W(i+k<=n&&j+k<=n&&!(s[i+k]^s[j+k])) ++k;H[R[i]]=k;
}
}
public:
I void Init(CI len,int* s) {n=len,GetSA(s),GetHeight(s);}//初始化
I LL GetAns() {Reg LL t=1LL*n*(n+1)>>1;for(RI i=1;i<=n;++i) t-=H[i];return t;}//计算答案
}S;
int main()
{
freopen("input8.txt","r",stdin),freopen("output8.txt","w",stdout);
RI Tpos,Ttot,i;F.read(Tpos,Ttot);W(Ttot--)
{
for(F.read(n),i=1;i<=n;++i) F.read(a[i]);//读入
S.Init(n,a),F.writeln(S.GetAns());//求解
}return F.clear(),0;
}
子任务\(9\)
同样是通过造小数据,可发现这题就是求平面最近点对。
用计算几何做即可。
代码如下:
#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define N 1000000
#define DB double
#define INF 1e9
#define dis(A,B) sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y))
#define min(x,y) ((x)<(y)?(x):(y))
#define Gmin(x,y) (x>(y)&&(x=(y)))
using namespace std;
int n,s[N+5];
struct Point//存储点
{
DB x,y;
I friend bool operator < (Con Point& x,Con Point& y) {return x.x==y.x?x.y<y.y:x.x<y.x;}//按x坐标排序
}p[N+5];
class FastIO
{
private:
#define FS 100000
#define tc() (A==B&&(B=(A=FI)+fread(FI,1,FS,stdin),A==B)?EOF:*A++)
#define tn(x) (x<<3)+(x<<1)
#define D isdigit(c=tc())
char c,*A,*B,FI[FS];
public:
I FastIO() {A=B=FI;}
Tp I void read(Ty& x) {x=0;W(!D);W(x=tn(x)+(c&15),D);}
Ts I void read(Ty& x,Ar&... y) {read(x),read(y...);}
}F;
I bool cmp(CI x,CI y) {return p[x].y<p[y].y;}//按y坐标排序
I double Solve(CI l,CI r)//分治
{
if(!(l^r)) return INF;if(r-l==1) return dis(p[l],p[r]);RI i,j,t=0,mid=l+r>>1;//判断边界情况
Reg DB d1=Solve(l,mid),d2=Solve(mid+1,r),d3,d=min(d1,d2);//分治两个区间,求答案
for(i=l;i<=r;++i) fabs(p[mid].x-p[i].x)<=d&&(s[++t]=i);//将可能符合条件的点的编号加入数组
for(sort(s+1,s+t+1,cmp),i=1;i<=t;++i) for(j=i+1;j<=t&&p[s[j]].y-p[s[i]].y<=d;++j) d3=dis(p[s[i]],p[s[j]]),Gmin(d,d3);//排序后用可能符合条件的点对更新答案
return d;//返回答案
}
int main()
{
freopen("input9.txt","r",stdin),freopen("output9.txt","w",stdout);
RI Tpos,Ttot,i,x,y;F.read(Tpos,Ttot);W(Ttot--)
{
for(F.read(n),i=1;i<=n;++i) F.read(x,y),p[i].x=x,p[i].y=y;//读入数据
sort(p+1,p+n+1),printf("%.3lf\n",Solve(1,n));//排序,然后分治输出答案
}return 0;
}
子任务\(10\)
最神奇的一个子任务。
这题的程序连第一个输入都会输出“\(invalid\ input!\)”
这时我便大胆猜想:这题就是输出\(10\)个“\(invalid\ input!\)”
结果真过了。
关于洛谷题目的吐槽
以上便是这道题的全部解法,这在\(UOJ\)上是可以轻松过的。
但可惜洛谷上交不了这么大的文件,结果只能写成代码,将第一个子任务直接搞,其余子任务打表输出答案。
\(AC\)代码如下:
#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
using namespace std;
class Subtask1Solver//处理第一个子任务
{
private:
int v[27]={0,'y','f','r','b','k','g','i','m','u','j','v','p','h','a','t','d','s','n','e','l','o','z','c','x','w','q'};
public:
I void Solve()
{
RI Ttot,i,len;Reg char c;Reg string s;scanf("%d",&Ttot);W(Ttot--)
{
for(cin>>s,len=s.length(),i=0;i^len;++i) putchar(v[s[i]&31]);
putchar('\n');
}
}
}S;
//以下为打表代码
I void Print2() {puts("106491\n189151\n42510\n93772\n32326\n6890\n94677\n168190\n66840\n93722");}
I void Print3() {puts("126\n126\n178\n252\n252\n626\n1982\n6268\n14567\n17730\n");}
I void Print4() {puts("68\n132\n171\n138\n225\n6592\n621318\n64147302\n1588039630\n6348298844");}
I void Print5() {puts("531842264\n3996089551\n1217487770\n13846806112\n2258552000\n12273908750\n31068785149\n453868136017\n7989258282893\n3571890382468");}
I void Print6() {puts("1159833908\n380176501\n1615846343\n1005775280\n1900756444\n139818805\n2130798985\n1503185154\n433569593\n988651389");}
I void Print7() {puts("880\n31080\n325200\n4449880\n135637352\n584509280\n72434344904\n306591086320\n2055466926488\n8643257847824");}
I void Print8() {puts("51\n108\n153\n4929\n124260\n498810\n12491602\n49971923\n2739460784\n499996516402");}
I void Print9() {puts("2.236\n69.527\n8.944\n10.440\n10.198\n1.414\n57.489\n10.770\n5.000\n8.544");}
I void Print10() {for(RI i=1;i<=10;++i) puts("invalid input!");}
int main()
{
RI Tpos;switch(scanf("%d",&Tpos),Tpos)
{
case 1:S.Solve();break;case 2:Print2();break;
case 3:Print3();break;case 4:Print4();break;
case 5:Print5();break;case 6:Print6();break;
case 7:Print7();break;case 8:Print8();break;
case 9:Print9();break;case 10:Print10();break;
}return 0;
}