NOIP2016 T4 魔法阵

题面

这里写图片描述

思路

本题暴力思路很简单,枚举判断就好(有45分啊)

代码
#include<bits/stdc++.h>
using namespace std;
struct node{int x;int y;}w[40005];
int t[40005][4],n,m;
bool cmp(node p,node q){return p.x<q.x;}
int main()
{
 scanf("%d%d",&n,&m);
 for (int i=1;i<=m;i++) scanf("%d",&w[i].x),w[i].y=i;
 sort(w+1,w+m+1,cmp);
 for (int a=1;a<=m;a++)
  for (int b=1;b<=m;b++)
   for (int c=1;c<=m;c++)
    for (int d=1;d<=m;d++)
    if(w[a].x<w[b].x&&w[b].x<w[c].x&&w[c].x<w[d].x&&w[b].x-w[a].x==(w[d].x-w[c].x)*2&&w[b].x-w[a].x<(w[c].x-w[b].x)*1.0/3)
     {
      t[w[a].y][1]++;
      t[w[b].y][2]++;
      t[w[c].y][3]++;
      t[w[d].y][4]++;
     }
    for (int i=1;i<=m;i++) cout<<t[i][1]<<" "<<t[i][2]<<" "<<t[i][3]<<" "<<t[i][4]<<endl; 
    return 0;
} 

但想得满分就没那么容易了,需要用到数轴分析
B-A=2(D-C)
B-A<(C-B)/3
所以设D-C为t
B-A=t
B-A<(C-B)/3=>C-B>6(B-A)=>6t+K=C-B
这里写图片描述
接下来就可以枚举t和d和a了,通过t与d和a推出其他点的位置(不用枚举所有,有范围的),不过有个优化,桶排一遍后用乘法原理优化,会快得多。

代码

#include <bits/stdc++.h>
#define MAXN 50010
using namespace std;
int n,m;
int a[MAXN],b[MAXN],c[MAXN],d[MAXN];
int x[MAXN],tt[MAXN];
int main(){
    cin>>n>>m;
    for(int i=1;i<=m;i++) cin>>x[i],tt[x[i]]++;
    for(int t=1;t*9<n;t++){
        int sum=0;
        for(int dx=9*t+2;dx<=n;dx++){
            int ax=dx-9*t-1;
            int bx=ax+2*t;
            int cx=dx-t;
            sum+=tt[ax]*tt[bx];
            c[cx]+=tt[dx]*sum;
            d[dx]+=tt[cx]*sum;
        }
        sum=0;
        for(int ax=n-9*t-1;ax;ax--){
            int bx=ax+2*t;
            int cx=bx+6*t+1;
            int dx=ax+9*t+1;
            sum+=tt[cx]*tt[dx];
            a[ax]+=tt[bx]*sum;
            b[bx]+=tt[ax]*sum;
        }
    }
    for(int i=1;i<=m;i++) cout<<a[x[i]]<<" "<<b[x[i]]<<" "<<c[x[i]]<<" "<<d[x[i]]<<endl;
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值