首页 > 其他分享 >P2119 [NOIP2016 普及组] 魔法阵

P2119 [NOIP2016 普及组] 魔法阵

时间:2024-07-31 22:51:14浏览次数:7  
标签:P2119 NOIP2016 const int 魔法阵 long mp ans define

P2119 [NOIP2016 普及组] 魔法阵

传送门

1

我们可以先写出\(O(m^4)\)的暴力

#include <bits/stdc++.h>  
#define int long long  
#define PII pair<int, int>  
using namespace std;  
const int inf = 0x3f3f3f3f;  
const int MOD = 1e9 + 7, N = 4e4 + 5;  
int n, m, ans[N][4];  
  
struct Node  
{  
    int x, id;  
    friend bool operator< (Node x, Node y)  
    { return x.x < y.x; }  
}x[N];  
  
signed main()  
{  
    scanf("%lld%lld", &m, &n);  
    for (int i = 1; i <= n; ++i)  
        scanf("%lld", &x[i].x), x[i].id = i;  
    sort(x + 1, x + 1 + n);  
    for (int a = 1; a <= n; ++a)  
    {  
        for (int b = a + 1; b <= n; ++b)  
        {  
            if (x[a].x == x[b].x) continue;  
            for (int c = n; c > b; --c)  
            {  
                if (4 * x[b].x >= 3 * x[a].x + x[c].x) break;  
                if (x[b].x == x[c].x) continue;  
                for (int d = c + 1; d <= n; ++d)  
                {  
                    if (x[c].x == x[d].x) continue;  
                    if (x[b].x - x[a].x != 2 * (x[d].x - x[c].x)) continue;  
                    ++ans[x[a].id][0], ++ans[x[b].id][1], ++ans[x[c].id][2], ++ans[x[d].id][3];  
                }  
            }  
        }  
    }  
    for (int i = 1; i <= n; ++i)  
        printf("%lld %lld %lld %lld\n", ans[i][0], ans[i][1], ans[i][2], ans[i][3]);  
    return 0;  
}

其实这份代码是优化过一点的
比如

for (int c = n; c > b; --c)  
    if (4 * x[b].x >= 3 * x[a].x + x[c].x) break;  

把\(c\)反着循环,\(c\)会越来越小,如果这条式子现在满足不了,以后也满足不了
分数\(65pts\)

2

接着我们可以看到\(n\)的数据范围比\(m\)小
就会想到计数数组
可写出\(O(n^4)\)的暴力

#include <bits/stdc++.h>
#define int long long
#define PII pair<int, int>
using namespace std;
const int inf = 0x3f3f3f3f;
const int MOD = 1e9 + 7, N = 4e4 + 5;
int n, m, ans[N][4], mp[N], x[N];

signed main()
{
    // freopen("magic.in", "r", stdin);
    // freopen("magic.out", "w", stdout);
    scanf("%lld%lld", &m, &n);
    for (int i = 1; i <= n; ++i)
        scanf("%lld", &x[i]), ++mp[x[i]];
    for (int a = 1; a <= m; ++a)
    {
        if (!mp[a]) continue;
        for (int b = a + 1; b <= m; ++b)
        {
            if (!mp[b]) continue;
            for (int c = m; c > b; --c)
            {
                if (!mp[c]) continue;
                if (4 * b >= 3 * a + c) break;
                for (int d = c + 1; d <= m; ++d)
                {
                    if (!mp[d]) continue;
                    if (b - a != 2 * (d - c)) continue;
                    int tmp = mp[a] * mp[b] * mp[c] * mp[d];
                    ans[a][0] += tmp / mp[a], ans[b][1] += tmp / mp[b];
                    ans[c][2] += tmp / mp[c], ans[d][3] += tmp / mp[d];
                }
            }
        }
    }
    for (int i = 1; i <= n; ++i)
        printf("%lld %lld %lld %lld\n", ans[x[i]][0], ans[x[i]][1], ans[x[i]][2], ans[x[i]][3]);
    return 0;
}

分数: \(75pts\)

3

因为题目中说了 \(X_b-X_a=2(X_d-X_c)\)
所以,我们可以只枚举\(X_a, X_b, X_c\)

#include <bits/stdc++.h>
#define int long long
#define PII pair<int, int>
using namespace std;
const int inf = 0x3f3f3f3f;
const int MOD = 1e9 + 7, N = 4e4 + 5;
int n, m, ans[N][4], mp[N], x[N];

signed main()
{
    // freopen("magic.in", "r", stdin);
    // freopen("magic.out", "w", stdout);
    scanf("%lld%lld", &m, &n);
    for (int i = 1; i <= n; ++i)
        scanf("%lld", &x[i]), ++mp[x[i]];
    for (int a = 1; a <= m; ++a)
    {
        if (!mp[a]) continue;
        for (int b = a + 1; b <= m; ++b)
        {
            if (!mp[b]) continue;
            if ((b - a) % 2) continue; // 因为式子是(b - a + 2 * c) / 2,c * 2一定是偶数,那么 b - a 也得是偶数
            for (int c = m; c > b; --c)
            {
                if (!mp[c]) continue;
                if (4 * b >= 3 * a + c) break;
                int d = (b - a + 2 * c) / 2;
                if (!mp[d]) continue;
                int tmp = mp[a] * mp[b] * mp[c] * mp[d];
                ans[a][0] += tmp / mp[a], ans[b][1] += tmp / mp[b];
                ans[c][2] += tmp / mp[c], ans[d][3] += tmp / mp[d];
            }
        }
    }
    for (int i = 1; i <= n; ++i)
        printf("%lld %lld %lld %lld\n", ans[x[i]][0], ans[x[i]][1], ans[x[i]][2], ans[x[i]][3]);
    return 0;
}

分数: \(85pts\)

4

我们可以知道
输入图片说明
这样, 中间的\(>6x\)的数量可以用后缀和处理

\[\displaystyle C[i]+=\sum_{j=1}^{j+8x<i}mp[j]\times mp[j+2t]\times mp[i+t] \\ C[i] += mp[i+t]*\sum^{j+8t<i}_{j=1}cnt[j]\times cnt[j+2t] \\ \]

#include <bits/stdc++.h>  
#define int long long  
#define PII pair<int, int>  
using namespace std;  
const int inf = 0x3f3f3f3f;  
const int MOD = 1e9 + 7, N = 4e4 + 5;  
int n, m, ans[N][4], mp[N], val[N];  
  
signed main()  
{  
    // freopen("magic.in", "r", stdin);  
    // freopen("magic.out", "w", stdout);  
    scanf("%lld%lld", &m, &n);  
    for (int i = 1; i <= n; ++i)  
        scanf("%lld", &val[i]), ++mp[val[i]];  
    for (int x = 1; 9 * x + 1 <= n; ++x)  
    {  
        int sum = 0;  
        int x7 = x * 7, x8 = x * 8, x9 = x * 9, x2 = x * 2;  
        for (int i = x9 + 2; i <= n; ++i)  
        {  
            sum += mp[i - x7 - 1] * mp[i - x9 - 1];  
            ans[i - x][2] += mp[i] * sum;  
            ans[i][3] += mp[i - x] * sum;  
        }  
        sum = 0;  
        for (int i = n - x9 - 1; i >= 1; --i)  
        {  
            sum += mp[i + x8 + 1] * mp[i + x9 + 1];  
            ans[i][0] += mp[i + x2] * sum;  
            ans[i + x2][1] += mp[i] * sum;  
        }  
    }  
    for (int i = 1; i <= n; ++i)  
        printf("%lld %lld %lld %lld\n", ans[val[i]][0], ans[val[i]][1], ans[val[i]][2], ans[val[i]][3]);  
    return 0;  
}

标签:P2119,NOIP2016,const,int,魔法阵,long,mp,ans,define
From: https://www.cnblogs.com/wanghaoze121126/p/18335659

相关文章

  • 2016 CSP-J/NOIP万字长文复赛真题题解——秒杀T1 买铅笔,T2 回文日期,T3 海港,T4 魔法
    [NOIP2016普及组]买铅笔题干[NOIP2016普及组]买铅笔题目背景NOIP2016普及组T1题目描述P老师需要去商店买nnn支铅笔作为小朋友们参加NOIP的礼物。她发现......
  • [lnsyoj166/luoguP2822/NOIP2016提高组] 组合数问题
    题意原题链接给定\(n,m,k\),对于所有的\(0\lei\len,0\lej\lemin\{i,m\}\),有多少对\((i,j)\)满足\(k|(^i_j)\)sol在解决组合数问题时,若遇到\(n,m\le2000\)的情况,可以使用递推法(杨辉三角)来进行\(O(n^2)\)的预处理,再\(O(1)\)直接调用递推法求组合数\[(^n_m)=(^{n-1}_m)+(......
  • CSP历年复赛题-P2119 [NOIP2016 普及组] 魔法阵
    原题链接:https://www.luogu.com.cn/problem/P2119题意解读:在一组数里找出所有的Xa,Xb,Xc,Xd的组合,使得满足Xa<Xb<Xc<Xd,Xb-Xa=2(Xd-Xc),Xb-Xa<(Xc-Xb)/3,并统计出每个数作为A,B,C,D出现的次数。解题思路:1、枚举(O(n^4))首先想到的是通过4重循环枚举所有可能的Xa,Xb,Xc,Xd,然后判......
  • CSP历年复赛题-P2058 [NOIP2016 普及组] 海港
    原题链接:https://www.luogu.com.cn/problem/P2058题意解读:计算24小时时间窗口内不同国家的数量,是队列的典型应用。解题思路:本题需要用到两个关键的数据结构:队列、数组队列用来保存24小时内到达的船的时间,数组用来保存24小时内每个国家有多少人每到一只船,需要把时间放入队列,如......
  • CSP历年复赛题-P2010 [NOIP2016 普及组] 回文日期
    原题链接:https://www.luogu.com.cn/problem/P2010题意解读:计算两个日期之间有多少个日期是回文。解题思路:如果通过枚举两个日期之间的所有日期,然后判断回文,则会有几个问题:枚举数据规模在10^7级别,再加上对于日期加一天、判断回文等处理,有可能超时,而且对日期进行加一天、判断回......
  • P2831 [NOIP2016 提高组] 愤怒的小鸟
    思路状压+优化代码#include<iostream>#include<stdio.h>#include<algorithm>#include<string>#include<cmath>#include<string.h>#defineR(x)x=read()#defineFor(i,j,n)for(inti=j;i<=n;++i)usingnamespac......
  • 洛谷之P1563 [NOIP2016 提高组] 玩具谜题
    题目 [NOIP2016提高组]玩具谜题题目背景NOIP2016提高组D1T1 题目描述小南有一套可爱的玩具小人,它们各有不同的职业。有一天,这些玩具小人把小南的眼镜藏了起来。小南发现玩具小人们围成了一个圈,它们有的面朝圈内,有的面朝圈外。如下图: 这时singer告诉小南一个谜......
  • 洛谷题单指南-线性表-P2058 [NOIP2016 普及组] 海港
    原题链接:https://www.luogu.com.cn/problem/P2058题意解读:计算24小时时间窗口内不同国家的数量,是队列的典型应用。解题思路:本题需要用到两个关键的数据结构:队列、数组队列用来保存24小时内到达的船的时间,数组用来保存24小时内每个国家有多少人每到一只船,需要把时间放入队列,如......
  • P1563 [NOIP2016 提高组] 玩具谜题
    1.题目介绍2.题解2.1模拟思路有一个大坑,题目给你的小人顺序是按逆时针给的,不是顺时针!!!跟顺时针相比掉一下顺序就行。看似一共有四种情况:[0,0],[0,1],[1,0],[1,1],其实可以简化分为两种情况,因为[0,0]和[1,1]都代表你要顺时针数,[1,0],[0,1]都代表你要逆时针数代码#include<b......
  • Luogu P1563 [NOIP2016 提高组] 玩具谜题
    [NOIP2016提高组]玩具谜题\(link\)题目背景NOIP2016提高组D1T1题目描述小南有一套可爱的玩具小人,它们各有不同的职业。有一天,这些玩具小人把小南的眼镜藏了起来。小南发现玩具小人们围成了一个圈,它们有的面朝圈内,有的面朝圈外。如下图:这时singer告诉小南一个谜题:“......