• 【洛谷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;
    }
    
  • 相关阅读:
    盛最多水的容器
    除自身以外数组的乘积
    组合总和
    旋转图像
    找到所有数组中消失的数字
    RSA加密、签名机制
    SpringBoot-从新建一个项目看起
    linux下vi命令修改文件及保存的使用方法
    集合
    第一个注解式的SpringMVC项目
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/Luogu5246.html
Copyright © 2020-2023  润新知