P2119 魔法阵

题目描述

六十年一次的魔法战争就要开始了,大魔法师准备从附近的魔法场中汲取魔法能量。

大魔法师有 m 个魔法物品,编号分别为 1,2,m。每个物品具有一个魔法值,我们用 Xi 表示编号为 i 的物品的魔法值。每个魔法值 Xi 是不超过 n 的正整数,可能有多个物品的魔法值相同。

大魔法师认为,当且仅当四个编号为 a,b,c,d 的魔法物品满足 Xa<Xb<Xc<Xd, Xb-Xa=2(Xd-Xc)Xa<Xb<Xc<XdXbXa=2(XdXc),并且 Xb-Xa<(Xc-Xb)/3XbXa<(XcXb)/3 时,这四个魔法物品形成了一个魔法阵,他称这四个魔法物品分别为这个魔法阵的 A 物品,B 物品,C 物品,D 物品。

现在,大魔法师想要知道,对于每个魔法物品,作为某个魔法阵的 A 物品出现的次数,作为 B 物品的次数,作为 C 物品的次数,和作为 D 物品的次数。

输入格式

第一行包含两个空格隔开的正整数 n,m。

接下来 m 行,每行一个正整数,第 i+1 行的正整数表示 Xi,即编号为 i 的物品的魔法值。

保证 1n15000,1m40000,1Xin。每个 Xi 是分别在合法范围内等概率随机生成的。

输出格式

共 m 行,每行 4 个整数。第 i 行的 4 个整数依次表示编号为 i 的物品作 为 A,B,C,D物品分别出现的次数。

保证标准输出中的每个数都不会超过 10^9。每行相邻的两个数之间用恰好一个空格隔开。

输入输出样例

输入

30 8
1
24
7
28
5
29
26
24

输出

4 0 0 0
0 0 1 0
0 2 0 0
0 0 1 1
1 3 0 0
0 0 0 2
0 0 2 2
0 0 1 0

分析

根据玄学数学,易得n < 11是无解,即全输出0,否则它们一定满足AB=2*CD,BC<6*CD,AD>9*CD。那么我们只需要确定D,就可以确定C点,然后再找AB。同理,我们也可以通过找C来确定ABD。

程序

#include <bits/stdc++.h>

using namespace std;

int a[100001] , b[100001] , c[100001] , d[100001] , w[100001] , h[100001] , n , m , x , y;

int main()
{
    cin >> n >> m;
    if(n < 11)
    {
        for(int i = 1; i <= m; i++) 
            printf("0 0 0 0\n");
        return 0;
    }
    for(int i = 1; i <= m; i++)
    {
        cin >> h[i];
        w[h[i]]++;
    }
    for(int i = 1; i <= n / 9; i++)
    {
        x = 1 + 9 * i , y = 0;
        for(int j = 2 + 9 * i; j <= n; j++)
        {
            y +=w[j - x] * w[j - x + i + i];
            d[j] += y * w[j - i];
            c[j - i] += y * w[j];
        }  
        x=8 * i + 1 , y = 0;  
        for(int j = n - 9 * i - 1; j >= 1; j--)  
        {  
            y += w[j + x] * w[j + x + i];  
            a[j] += y * w[j + i + i];  
            b[j + i + i] += y * w[j];  
        }  
    }  
    for(int i = 1; i <= m; i++) 
        cout << a[h[i]] << ' ' << b[h[i]] << ' ' << c[h[i]] << ' ' << d[h[i]] << endl;
    return 0;
}

 

 

posted @ 2020-10-25 22:59  Tenderfoot  阅读(168)  评论(0编辑  收藏  举报