【洛谷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('
');//换行
	}return 0;
}

子任务(2)

先打表得到(n=1sim5)的输出结果分别为(2030,8082,18166,32282,50430)

考虑其每次增加的值分别为(6052,10084,14116,18148),而增加的值所相差的值都为(4032)

设第(i)个数为(f_i),则不难得到:

[f_i=2030+6052(i-1)+4032frac{(i-2)(i-1)}2=2016i^2+4i+10 ]

貌似做完了?

等等,这种式子肯定需要取模!

我们继续打表,可以发现在(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('
');}
        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)上,发现是这样一个式子:

[lfloorsqrt{frac ipi} floor ]

代码如下:

#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('
');}
        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('
');}
        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('
');}
        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('
');}
        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)

通过大量测试和猜测可得我们要求的式子为:

[sum_{i=1}^nsum_{j=1}^mgcd(i,j) ]

观察(input.txt),可以发现除了一组(100 1000)的数据外,其余的数据都满足(n=m)

(100 1000)的数据我们完全可以暴力求解。

否则,我们将(n=m)代入得到:

[sum_{i=1}^nsum_{j=1}^ngcd(i,j) ]

这应该是比较经典的式子,我们枚举(gcd)得:

[sum_{d=1}^nsum_{i=1}^{lfloorfrac nd floor}sum_{j=1}^{lfloorfrac nd floor}d[gcd(i,j)==1] ]

(d)提前得:

[sum_{d=1}^ndsum_{i=1}^{lfloorfrac nd floor}sum_{j=1}^{lfloorfrac nd floor}[gcd(i,j)==1] ]

而后半部分可以运用(phi)的定义转化,于是得到这样一个式子:

[sum_{d=1}^nd(2sum_{i=1}^{lfloorfrac nd floor}phi(i)-1) ]

(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('
');}
        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)

手造几组小数据,可发现这题求的是给定序列本质不同的子串个数。

后缀数组裸题,答案就是:

[frac{n(n+1)}2-sum_{i=1}^nHeight_i ]

代码如下:

#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('
');}
        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
",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('
');
			}
		}
}S;
//以下为打表代码
I void Print2() {puts("106491
189151
42510
93772
32326
6890
94677
168190
66840
93722");}
I void Print3() {puts("126
126
178
252
252
626
1982
6268
14567
17730
");}
I void Print4() {puts("68
132
171
138
225
6592
621318
64147302
1588039630
6348298844");}
I void Print5() {puts("531842264
3996089551
1217487770
13846806112
2258552000
12273908750
31068785149
453868136017
7989258282893
3571890382468");}
I void Print6() {puts("1159833908
380176501
1615846343
1005775280
1900756444
139818805
2130798985
1503185154
433569593
988651389");}
I void Print7() {puts("880
31080
325200
4449880
135637352
584509280
72434344904
306591086320
2055466926488
8643257847824");}
I void Print8() {puts("51
108
153
4929
124260
498810
12491602
49971923
2739460784
499996516402");}
I void Print9() {puts("2.236
69.527
8.944
10.440
10.198
1.414
57.489
10.770
5.000
8.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;
}
原文地址:https://www.cnblogs.com/chenxiaoran666/p/Luogu5246.html