【WHUST 2016 Individual Contest #1】解题报告

    第一次个人赛自我感觉还好,毕竟抱着大腿们都要完虐我的心态下,很快地把签到题都搞出来了。ACM主要是靠脑子,我这种卡壳常客居然一鼓作气前7题写出来了到第八个题才卡……但是一卡就是三个小时……还是自己的问题,队友都在刷专题搞大新闻,我就默默写点读题解题思路好了,但愿我们队组队赛时我也能有这个水平吧。(育肥君要加油哦)





A - SwapSort(CodeForces 489A)

题意:问一个数列使用小于N次交换变换成排序后的数列的一个方案。(N<=3000)

思路:上来就想类似归并和快排都是NlogN级别的交换,题目要求的是N次以内的一种交换,肯定不能直接在排序过程里下手。不管怎么样,我们可以快排很轻松地得到结果,于是问题变成了怎么从一个数列变成另一个已知数列:很显然,我们从1到N每个数都换到该在的位置(先处理1位置,如果1位置上不是答案1位置上的数,那么把现在1位置的数跟答案1位置的数进行一次交换,再去处理2位置……依此类推)因为每次让一个数归位要交换一次,所以至多交换了N次,Problem Solved.

#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>

using namespace std;

int N,a[3010],b[3010];
int ans,x[3010],y[3010];
int main()
{
	scanf("%d",&N);
	for(int i=1;i<=N;i++)
	{
		scanf("%d",&a[i]);
		b[i]=a[i];
	}
	sort(b+1,b+N+1);
	ans=0;
	for(int i=1;i<=N;i++)
	{
		if(a[i]==b[i])continue;
		int j=i+1;
		while(a[j]!=b[i])j++;
		ans++;
		x[ans]=i;
		y[ans]=j;
		a[j]=a[i];
		a[i]=b[i];
	}
	printf("%d\n",ans);
	for(int i=1;i<=ans;i++)
	{
		printf("%d %d\n",x[i]-1,y[i]-1);
	}
	return 0;
}

B - Unbearable Controversy of Being(CodeForces 489D)

题意:3000个点30000条边的有向图里找到如图所示的四点对的个数。(b和d无顺序之分)


思路:一开始做完了A看到这个题除了枚举并没有什么想法……就去做其它签到题了。回过头来一想,其实你不需要枚举四个点,你要找的是所有方案数,其实这个图就可以翻译为:两条从a出来可以两步到达c的路径。这样的基础上,我们枚举起点a,记录a走两步(dfs两层)到所有点的的路的条数,计算C(2)(k)就好了。

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<iostream>
#include<vector>
using namespace std;

int T,N,M;
vector <int> p[3010];
int walked[3010];
long long rhombi;
void dfs(int node,int layer)
{
	if(layer==3){walked[node]++;return;}
	for(unsigned int i=0;i<p[node].size();i++)
		dfs(p[node][i],layer+1);
}
int main()
{
		rhombi=0;
		scanf("%d%d",&N,&M);
		int tempa,tempb;
		for(int i=1;i<=M;i++)
		{
			scanf("%d%d",&tempa,&tempb);
			p[tempa].push_back(tempb);
		}
		for(int i=1;i<=N;i++)
		{
			memset(walked,0,sizeof(walked));
			dfs(i,1);
			for(int j=1;j<=N;j++)
			{
				if(i==j)continue;
				if(walked[j]>=2)
				{
					rhombi+=((long long)walked[j]*(walked[j]-1)/2);
				}
			}
		}
		printf("%I64d\n",rhombi);
	
	
	return 0;
}


C - Hiking(CodeForces 489E)

题意:一条数轴,从0出发。有N(N<=1000)个歇脚点,按离0远近给出,旅行者要走到最后一个歇脚点去。旅行者有个给出的定值L(L<=10^5),是他每天都想走的距离,事与愿违,他走不了L米就会有不高兴值,而每天他都要走到歇脚点才能停。最终不高兴的总值为:∑(sqrt(实际距离(x[i]-x[j])与理想距离(L)差))/∑(所有停留过的歇脚点的风景值(b[i]))。如何选择方案让不高兴值最小,按顺序输出要停留的落脚点。

思路:%%%wrd.我只想到了dp,然而直接dp是不可以的,你每次A/B形式的答案上分子分母都要加值(A+x)/(B+y),这就无法保证局部最优性,也就是说走到第i个落脚点的最优解不一定比次优解好(好 是指往后走答案更优)。——该怎么办呢?比赛中就战略性放弃了……实际上这是个0/1分数dp,太久没写了都忘完了……在分子分母都在变的情况下,我们可以选择二分答案:如果我们有个答案ans,那么对式子进行变换:∑( sqrt( abs(x[i]-x[j]-L) ) - ans*b[i] )=0。如果有方案能找出更小的ans,那么等号应该变为大于号——同时,这个式子是满足局部最优性的,记录dp[i]=dp[j]+sqrt(abs(x[i]-x[j]-L))-ans*b[i],使dp[i]最小就能最终得出dp[N],也为最小,如果dp[N]>0,那么ans不满足条件,要更大;dp[N]<0,试图找更小的ans,要更小……最后要求的是路径,加一个数组记录i状态是从哪个j状态转移过来的,这样回溯过去就好了。

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<iostream>
#include<cmath>
using namespace std;

int N;
double L;
double x[1010],b[1010];
double dp[1010];
int pre[1010];
double ans;
void dfs(int node)
{
	if(node==0)return;
	dfs(pre[node]);
	printf("%d ",node);
}
//double abs(double temp){return temp>0?temp:(temp)*(-1);}
//double max(double a,double b){return a<b?b:a;}
bool check(double ans)
{
	dp[0]=0;
	for(int i=1;i<=N;i++)
	{
		dp[i]=sqrt(abs(x[i]-L))-ans*b[i];
		pre[i]=0;
		for(int j=1;j<i;j++)
		{
			double temp=dp[j]+sqrt(abs(x[i]-x[j]-L))-ans*b[i];
			if(temp<dp[i])
			{
				dp[i]=temp;
				pre[i]=j;
			}
		}
	}
	//printf("%.8lf\n",ans);
	if(dp[N]<0)
		return true;
	return false;
}
int main()
{
	//freopen("in.txt","r",stdin);
	scanf("%d%lf",&N,&L);
	for(int i=1;i<=N;i++)
		scanf("%lf%lf",&x[i],&b[i]);
	double l=0,r=1e6;
	double mid;
	while(r-l>1e-8)
	{
		if(check(mid=(l+r)/2))
		{
			r=mid;
		}
		else
		{
			l=mid;
		}
	}
	check(mid);
	dfs(N);
	return 0;
}

D - Special Matrices(CodeForces 489F)

题意:N*N(N<=500)的01矩阵,保证每一行每一列都是2个1,给定前M行的状态,求最多有多少种方案填充完整。

思路:又是思路不清晰没写出来的题,遗憾。限定每行每列都是两个1,其实每两列都是可以互换的,也就是说按行去考虑,当前填充到第i行时完全可以把填充了0个1的列移到一起,把填充了1个1的列移到一起,填充了2个1的列移动到一起,于是dp[i][j][k]表示填充i行有j列有1个1,有k列有0个1(N-j-k列已经有2个1)的方案数。其中i是一行一行的,可以用滚动数组压缩一维。思路难点在于想到列可以移动而且移动后还是可以记录方案数的

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<string>
using namespace std;

int give[510];
int N,M;
long long MOD;
long long dp[2][501][501];
int main()
{
	cin.sync_with_stdio(false);
	//scanf("%d%d%I64d\n",&N,&M,&MOD);
	cin>>N>>M>>MOD;
	string temp;
	for(int i=1;i<=M;i++)
	{
		cin>>temp;
		for(int i=1;i<=N;i++)
		{
			//scanf("%c",&temp);
			//cin>>temp;
			//give[i]+=(temp-'0');
			if(temp[i-1]=='1')
				give[i]++;
		}
		//scanf("\n");
	}
	int st_one=0,st_two=0;
	for(int i=1;i<=N;i++)
	{
		if(give[i]==1)
			st_one++;
		if(give[i]==2)
			st_two++;
	}
	
	dp[M&1][st_one][N-st_one-st_two]=1;
	
	int cur,pre;
	for(int i=M+1;i<=N;i++)
	{
		cur=i&1;
		pre=cur^1;
		memset(dp[cur],0,sizeof(dp[cur]));
		for(int j=0;j<=N;j++)
		{
			for(int k=0;k<=N;k++)
			{
				if(!dp[pre][j][k])continue;
				if(j>=2)
				{
					dp[cur][j-2][k]+=dp[pre][j][k]*(j-1)*j/2;
					dp[cur][j-2][k]%=MOD;
				}
				if(k>=2)
				{
					dp[cur][j+2][k-2]+=dp[pre][j][k]*(k-1)*k/2;
					dp[cur][j+2][k-2]%=MOD;
				}
				if(j>=1&&k>=1)
				{
					dp[cur][j][k-1]+=dp[pre][j][k]*j*k;
					dp[cur][j][k-1]%=MOD;
				}
			}
		}
	}
	//printf("%I64d\n",dp[N&1][0][0]);
	cout<<dp[N&1][0][0]<<endl;
	
	return 0;
}

E - BerSU Ball(CodeForces 489B)

题意:二分图上只对权值差小于等于1的点连边,问最大匹配数。

思路:好裸的二分图最大匹配——等等,这题并不需要二分图——贪心地从最小的值开始匹配,如果能匹配上就匹配,如果不能匹配上就让小一点的那个走开,队列里下一个继续匹配……嗯,就这样。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<iostream>
#include<cmath>


using namespace std;

int n,m;
int a[110],b[110];
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
		scanf("%d",&a[i]);
	sort(a+1,a+n+1);
	scanf("%d",&m);
	for(int j=1;j<=m;j++)
		scanf("%d",&b[j]);
	sort(b+1,b+m+1);
	
	int pa=1,pb=1,pairs=0;
	while(pa<=n&&pb<=m)
	{
		if(abs(a[pa]-b[pb])<=1)
		{
			pa++;
			pb++;
			pairs++;
			continue;
		}
		if(a[pa]<b[pb])
			pa++;
		else
			pb++;
		
	}
	
	printf("%d\n",pairs);
	
	return 0;
}

F - Given Length and Sum of Digits...(CodeForces 489C)

题意:给定一个数字的长度,和该数字的各个位上数字总和,求满足条件的该数字最小为多少,最大为多少。

思路:就是个模拟,最小的时候从最高位开始填100...99,最大的时候从最高位开始填999...00,最初还WA了一发。。。因为特判长度为1,数字总和为0.。。。Should've pay more attention to details.

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>

using namespace std;

int dig[101];
int main()
{
	int m,s;
	scanf("%d%d",&m,&s);
	if(9*m<s){printf("-1 -1\n");return 0;}
	if(m>1&&s<1){printf("-1 -1\n");return 0;}
	if(m==1&&s==0){printf("0 0\n");return 0;}
	int temps=1;
	memset(dig,0,sizeof(0));
	dig[1]=1;
	int k=m;
	while(temps<s)
	{
		if(s-temps>9)
		{
			dig[k]=9;
			k--;
			temps+=9;
		}
		else
		{
			dig[k]+=s-temps;
			k--;
			temps+=(s-temps);
		}
	}
	for(int i=1;i<=m;i++)
		printf("%d",dig[i]);
	printf(" ");
	memset(dig,0,sizeof(dig));
	temps=0;
	k=1;
	while(temps<s)
	{
		if(s-temps>=9)
		{
			dig[k]=9;
			k++;
			temps+=9;
		}
		else
		{
			dig[k]=s-temps;
			k++;
			temps+=(s-temps);
		}
	}
	for(int i=1;i<=m;i++)
		printf("%d",dig[i]);
	printf("\n");
	return 0;
}


G - zxa and set(HDU5680)

题意:有个N个数的集合,它的每个非空子集的最小数为该子集的值,问你 包含偶数个数的子集总和 与 包含奇数个数的子集的总和 之差。

思路:按N个数从小到大排序后,第i个数字会在个数为j的集合中被计算C(j-1)(N-i)次,所以j为奇数时,

ans+=a[i]*C[j-1][N-i];
j为偶数时
ans-=a[i]*C[j-1][N-i];
嗯,就酱紫。

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<cmath>
#include<algorithm>

using namespace std;

int T;
int N;
long long a[40];
long long C[40][40];
long long ans;
int main()
{
	C[0][0]=1;
	C[0][1]=1;
	C[1][1]=1;
	for(int i=2;i<=30;i++)
	{
		C[0][i]=1;
		for(int j=1;j<i;j++)
		{
			C[j][i]=C[j-1][i-1]+C[j][i-1];
		}
		C[i][i]=1;
	}
	scanf("%d",&T);
	while(T--)
	{
		ans=0;
		
		scanf("%d",&N);
		for(int i=1;i<=N;i++)
			scanf("%d",&a[i]);
		sort(a+1,a+N+1);
		for(int i=1;i<=N;i++)
		{
			for(int j=1;j<=N-i+1;j++)
			{
				if(j%2==0)
					ans-=a[i]*C[j-1][N-i];
				else
					ans+=a[i]*C[j-1][N-i];
				//printf("%d %d %I64d\n",i,j,a[i]*C[j-1][N-i]);
			}
		}
		
		printf("%I64d\n",abs(ans));
	}
	return 0;
}

H - zxa and wifi(HDU5681)

待补。dp。增加冗余项使dp复杂度降低。



I - ztr loves lucky numbers(HDU5676)

题意:找到最小的比给定数字大的由相同个数个4和7组成的数字。

思路:有10^5组数据而且每次给的N都是10^18以内,所以只能拿位数一位一位模拟。首先判断是不是奇数位,如果是偶数位,挨位填4还是7。要注意的细节是:

1.记录一个overwhelm代表是否前面的位已经比给定值大了,如果overwhelm==1那么有4取4,没4取7。

2.不止要记录4的个数,也要记录7的个数。当你填7填的不够了,要退回去把最近的一个4换成7,再从这个4换成7的位重新往后填。

然而,这题根本不需要这么麻烦的模拟——%%%gss。把10^18以内的所有47“幸运数”记下来就够了,每次直接在set里lowerbound就好了。orz

给出自己又长又丑的模拟代码。

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<iostream>

using namespace std;

int ans[20];
int main()
{
	cin.sync_with_stdio(false);
	int T;
	cin>>T;
	string str;
	while(T--)
	{
		cin>>str;
		int len=str.length();
		if(len%2==1)
		{
			len++;
			for(int i=1;i<=len/2;i++)
				printf("4");
			for(int i=1;i<=len/2;i++)
				printf("7");
			printf("\n");
			continue;
		}
		else
		{
			for(int i=1;i<=len/2;i++)
				ans[i]=7;
			for(int i=len/2+1;i<=len;i++)
				ans[i]=4;
			for(int i=1;i<=len;i++)
			{
				if(str[i-1]-'0'>ans[i])
				{
					len+=2;
					for(int i=1;i<=len/2;i++)
						printf("4");
					for(int i=1;i<=len/2;i++)
						printf("7");
					printf("\n");
					goto NEXT;
				}
				if(str[i-1]-'0'<ans[i])
					break;
			}
			int fours=len/2,sevens=len/2;
			memset(ans,0,sizeof(ans));
			bool overwhelm=false;
			for(int k=1;k<=len;k++)
			{
				if(overwhelm)
				{
					if(fours)
					{
						ans[k]=4;
						fours--;
					}
					else
					{
						ans[k]=7;
						sevens--;
					}
				}
				else
				{
					int temp=str[k-1]-'0';
					if(temp==4)
					{
						if(fours)
						{
							ans[k]=4;
							fours--;
							continue;
						}
						else
						{
							ans[k]=7;
							sevens--;
							overwhelm=1;
							continue;
						}
					}
					if(temp==7)
					{
						if(sevens)
						{
							ans[k]=7;
							sevens--;
							continue;
						}
						else
						{
							int kk=k-1;
							while(ans[kk]==7)kk--;
							ans[kk]=7;
							for(int i=kk+1;i<k;i++)
								if(ans[i]==4)
									fours++;
								else
									sevens++;
							fours++;
							sevens--;
							overwhelm=1;
							k=kk;
							continue;
						}
					}
					if(temp<4)
					{
						if(fours)
						{
							overwhelm=1;
							ans[k]=4;
							fours--;
							continue;
						}
						else
						{
							overwhelm=1;
							ans[k]=7;
							sevens--;
							continue;
						}
					}
					if(temp>4&&temp<7)
					{
						overwhelm=1;
						ans[k]=7;
						sevens--;
						continue;
					}
					if(temp>7)
					{
						int kk=k-1;
						while(ans[kk]==7)kk--;
						ans[kk]=7;
						for(int i=kk+1;i<k;i++)
							if(ans[i]==4)
								fours++;
							else
								sevens++;
						fours++;
						sevens--;
						overwhelm=1;
						k=kk;
						continue;
					}
					
				}
			}
			for(int i=1;i<=len;i++)
				printf("%d",ans[i]);
			printf("\n");
		}
		NEXT:;
	}
	
	
	return 0;
}

J - KK's Steel(HDU5620)

题意:有N米长的钢筋,想切地越多越好,但是切出来的钢筋不能长度相同,而且任意三个钢筋不能组成三角形。

思路:不能组成三角形这个太严格了,三角形最长边要小于等于另两条边,也就是说如果当前集合里最大的是a1,a2,只有a3>=a1+a2才能添加到集合中去。于是逆向思维,最少有1,有2,因为钢筋个数尽可能多就添加最小的1+2=3进去,再添加2+3=5,3+5=8...斐波那契数列了。。。找到小于前n项和小于N的最大n就好了。

#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<iostream>
using namespace std;


long long N;
int tot;
long double steel[1000000];
int main()
{
	steel[1]=1;
	steel[2]=2;
	steel[3]=3;
	tot=3;
	while(tot<=1000000&&steel[tot]+steel[tot-1]<=1e18)steel[++tot]=steel[tot-1]+steel[tot-2];
	//long long temp=steel[tot];
	//cout<<temp<<endl;
	int T;
	scanf("%d",&T);
	while(T--)
	{
		scanf("%I64d",&N);
		int temp=0;
		long double m=0;
		long double n=N;
		while(n>=m)
		{
			temp++;
			m+=steel[temp];
		}
		cout<<temp-1<<endl;
	}
	
	return 0;
}

K - KK's Number(HDU5623)

题意:二人博弈。有N<=5*10^4个数字,轮流操作,每次操作可以取走任意个数,那么这次操作的得分为这些取走的数字中最小数字的值。问两人分数差最大为多少。

思路:得分是每次操作去给的,我当时居然没有反应过来……一看就是脑子太久不用迟钝了。GG

每次取都是从大的去取,而且一定不会留下相同的数字,于是预处理一下合并相同数字。

ans[i]代表取到第i个数字,两人差最大为多少。

有ans[i]=max(ans[i-1],a[i]-ans[i-1]);//ans[i]==ans[i-1]时是把第i个数跟之前的一起取掉,ans[i]==a[i]-ans[i-1]是只取当前数字,那么相当于在i-1时是敌手的先手。

嗯-m-,这样。

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<iostream>


using namespace std;

int T;
int N,n;
long long num[50010];
long long a[50010];
long long ans[50010];
int main()
{
	scanf("%d",&T);
	while(T--)
	{
		scanf("%d",&N);
		for(int i=1;i<=N;i++)
			scanf("%I64d",&num[i]);
		sort(num+1,num+N+1);
		n=1;
		a[1]=num[1];
		for(int i=2;i<=N;i++)
			if(num[i-1]!=num[i])
				a[++n]=num[i];
		ans[0]=0;
		for(int i=1;i<=n;i++)
		{
			ans[i]=max(ans[i-1],a[i]-ans[i-1]);
		}
		//for(int i=1;i<=n;i++)
		//	printf("%I64d ",ans[i]);
		printf("%I64d\n",ans[n]);
	}
	
	return 0;
}

L - Jam's store(HDU 5619)

题意:M个员工,N个顾客,排队修理东西,问最小总等待时间。

思路:写过类似的,可惜忘记了具体思路。OI老龄痴呆选手TAT……M和N都只有20,很明显不是状压就是网络流(或者奇怪的暴力)。

正解是最小费用最大流,建边时要注意到一个性质,在同一个员工的等待队伍里有k个人,第i个人要被等待k-i次(所有i后面的人都在等),于是倒过来,让最后一个顾客作为第一个顾客考虑,倒数第二个顾客作为第二个顾客考虑……这样的好处是,建边时,第i个在等待的人的边权是i*等待时间,这样400+个点跑最小费用最大流就搞定了。

(补题时WA了一发,因为模板是没有多组数据的,在改的时候清理没有清理干净p[0]数组……)XD


#include<fstream>
#include<cstring>
#include<vector>
#include<deque>
#include<cmath>
#include<iostream>
using namespace std;
const int SIZEN=501,INF=0x7FFFFFFF;
class EDGE
{
public:
	int u,v,c,w;
};
int cost,S,T;
int M,N;
int matrix[21][21];
vector <EDGE> edge;//所有边
vector <int> p[SIZEN];//点对应的边的编号
void CLEAR()
{
	edge.clear();
	for(int i=0;i<=N+N*M+1;i++)p[i].clear();
}
void Addedge(int u,int v,int c,int w)
{
	edge.push_back((EDGE){u,v,c,w});
	edge.push_back((EDGE){v,u,0,-w});
	int tmp=edge.size()-2;
	p[u].push_back(tmp);
	p[v].push_back(tmp+1);
}
bool SPFA()
{
	deque <int> q;
	//spfa
	bool boo[SIZEN]={0};
	int i,j,d[SIZEN],father[SIZEN]={0};
	for(i=0;i<=N+M*N+1;i++)d[i]=INF;
	q.push_back(S);
	d[S]=0;
	boo[S]=1;
	EDGE ed;
	while(!q.empty())
	{
		j=q.front();
		boo[j]=false;
		q.pop_front();
		for(i=0;i<p[j].size();i++)
		{
			ed=edge[p[j][i]];
			if(ed.c)
				if(d[ed.v]>d[j]+ed.w)
				{
					d[ed.v]=d[j]+ed.w;
					father[ed.v]=p[j][i];//father[]记录所来的边
					if(!boo[ed.v])
					{
						boo[ed.v]=1;
						q.push_back(ed.v);
					}
				}
		}
	}
	if(d[T]==INF)return false;//没有找到最短路
	
	//找到一条路径后
	//1.找流量
	i=T;
	int flow=INF;
	while(i!=S)
	{
		flow=min(edge[father[i]].c,flow);
		i=edge[father[i]].u;
	}
	//fo<<flow<<endl;
	cost+=flow*d[T];
	//2.减流量
	i=T;
	int now;
	while(i!=S)
	{
		now=father[i];
		edge[now].c-=flow;
		edge[now^1].c+=flow;
		i=edge[now].u;
	}
	return true;
}
int main()
{
	ios::sync_with_stdio(false);
	int Tests;
	cin>>Tests;
	while(Tests--)
	{
		cin>>M>>N;
		for(int i=1;i<=N;i++)
		{
			for(int j=1;j<=M;j++)
				cin>>matrix[i][j];
		}
		CLEAR();
		S=0;
		T=N+M*N+1;
		for(int i=1;i<=N;i++)
			Addedge(S,i,1,0);
		for(int i=1;i<=M;i++)
		{
			for(int j=1;j<=N;j++)
			{
				for(int k=1;k<=N;k++)
				{
					Addedge(k,N+(i-1)*N+j,1,j*matrix[k][i]);//K号顾客在i号员工处作为倒数第j个来repair的
				}
				Addedge(N+(i-1)*N+j,T,1,0);
			}
		
		}
		cost=0;
		while(SPFA());
		cout<<cost<<endl;
	}
	return 0;
}


这大概就是第一次吧(???)。题读起来还是觉得不舒服……CF跟HDU的英文题一看就能区分出来哪个是中国人出的题……不能怪出题人,要怪就怪自己思路跟出题人不一样,说明我还不是一个够格的ACMer。那。。。加油。





  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值