题目来这里:跟我飞飞飞(不要问我为什么,自己看前3篇题解)
还能怎么做,要么爆搜要么递归,要么超时要么栈溢出……
其实这次复赛的题几乎没有什么算法,数据结构也就3题算用了队列,全部是考思维。
此题正确思路:
先看看要满足的条件: Xa<Xb<Xc<Xd,Xb-Xa=2(Xd-Xc),且Xb-Xa<(Xc-Xb)/3
所以我们能得到一个图:
相信这个不难理解,结合上面的条件变能够看懂(其实最重要的第一步就是先画好图)。
i当然是正整数,所以当我们枚举时外层循环便是i,从多少到多少呢?
题告诉我们,数据中的数均不超过n,所以我们就是枚举到n……吗?显然可以看出,图中一共是>9i的,所以只需要枚举到n/9便可以了。
外层循环枚举i,那里面呢?也不需要abcd挨个枚举。
我们只需要先枚举最后的d,由d可以知道c和d的数量,d的数量便是它之前的a,b,c的数量的乘积(当然不可能是加起来),c也一样。
然后枚举最前面的a,由a又可以知道b,a的数量便是它之前的b,c,d的乘积,b一样。
可能有一点动态规划的思想。
就这些了,我知道你很懵逼,看看代码吧:
#include<cstdio> int h[40005],w[15005];//h为魔法值,w为每种魔法值出现的次数 int ans[15005][5];//答案不解释 int n,m; int main() { scanf("%d%d",&n,&m); for(int i=1;i<=m;i++) { scanf("%d",&h[i]); w[h[i]]++;//此物品次数++ } for(int i=1;i<=n/9;i++) { int a=1,d,tmp=0;//先默认a为1 for(d=i*9+2;d<=n;d++)//枚举d(a为整数,c-b要>6i,所以要加2) { tmp+=w[a+2*i]*w[a]; a++;//ab次数的乘积(本来最后可以写w[a++]的,但不知为什么有警告(不影响)) ans[d][4]+=tmp*w[d-i];//d的次数为ab次数乘c ans[d-i][3]+=tmp*w[d];//c的次数为ab次数乘d } tmp=0,d=n; for(a=n-9*i-1;a>=1;a--)//不能正着枚举a,因为这样tmp的累加就有问题了 { tmp+=w[d-i]*w[d]; d--; ans[a][1]+=tmp*w[a+2*i]; ans[a+2*i][2]+=tmp*w[a];//这些都和上面大同小异 } } for(int i=1;i<=m;i++) printf("%d %d %d %d ",ans[h[i]][1],ans[h[i]][2],ans[h[i]][3],ans[h[i]][4]);//输出 return 0; }
By WZY