ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Recover an RBS

2022-07-22 20:34:26  阅读:151  来源: 互联网

标签:int ll 位置 RBS base result Recover MOD


传送门
题意:

给出a, b序列,c序列刚开始有些位置是有值的,题目已经给出,其余位置为0,对于0的位置要求从a, b对应的位置取一个值,最后使整个c构成一个序列,问可以构成多少个可以构成的序列,结果对1e9 + 7取模

思路:

可以先确定哪些位置是确定不变的

  • 如果a, b的元素相等,那就是不变的
  • 去处理那些题目已经确定的位置,根据那些位置可以推出的其他所有位置的情况也只可能只有一个
  • 去处理那些题目已经确定的位置,根据那些位置可以推出的其他所有位置的情况也只可能只有一个

在已经得知那些确定的位置之后剩下的位置,可以发现如果可以跳来跳去去构成一个环,那对答案的贡献就是 * 2,所以问题就转换为剩下的位置可以构成多少个环,要判断数字环的话,可以用并查集,转换为连边的思想,记录数量为count, 最后的答案是\(2^{count}\)

点击查看代码
#include <bits/stdc++.h>
#define endl '\n'
#define IOS ios::sync_with_stdio(false);
#define PII pair<int, int>
using namespace std;
 
typedef long long ll;
const ll MOD = 1e9 + 7;
const int N = 1e5 + 10;
 
ll quick_pow(ll base, ll power)
{
    ll result = 1ll;
    while (power)
    {
        if (power & 1)  //当前的指数为奇数
        {
            result = (result % MOD * base % MOD) % MOD; //将当前多余出来的底数单独先记录下来,让他重新能够对半
        }
        base = (base % MOD * base % MOD) % MOD; //能够执行到这一步说明这个底数还可以对半相乘,或者这个对半相乘没有作用
        power >>= 1;    //如果为1的话,最后就为0了
    }
    return result;
}
 
int T, n;
int a[N], b[N], c[N], fa[N];
 
struct Node
{
    int a, b, c, id;
} aa[N], bb[N];
 
void Init()
{
    for (int i = 1; i <= n; ++i)
    {
        fa[i] = i;
    }
}
 
int find(int x)
{
    if (x == fa[x])
        return x;
    else
        return fa[x] = find(fa[x]);    
}
 
int main()
{
	IOS; cin.tie(0), cout.tie(0);
    cin >> T;
    while (T--)
    {
        cin >> n;
        queue<Node> q;
        map<int, int> mp;
        Init();
        for (int i = 1; i <= n; ++i)
        {
            cin >> a[i];
        }
        for (int i = 1; i <= n; ++i)
        {
            cin >> b[i];
        }
        for (int i = 1; i <= n; ++i)
        {
            cin >> c[i];
            if (c[i] != 0 || a[i] == b[i])  //两个位置的元素相同也是唯一确定的
            {
                if (a[i] == b[i])
                    c[i] = a[i];
                q.push({a[i], b[i], c[i], i});   //4个元素全插入
                mp[i] = 1;  //对位置进行标记
            }
        }
        for (int i = 1; i <= n; ++i)
        {
            aa[a[i]].a = a[i];
            aa[a[i]].b = b[i];
            aa[a[i]].c = c[i];
            aa[a[i]].id = i;
            bb[b[i]].a = a[i];
            bb[b[i]].b = b[i];
            bb[b[i]].c = c[i];
            bb[b[i]].id = i;
        }
 
        //先把肯定确定的位置数量给记录标记出来
        while (!q.empty())  //将确定位置的全标记
        {
            Node temp = q.front();
            q.pop();
            if (temp.a == temp.b)   //说明这a[i], b[i]相同,不用考虑
            {
                continue;
            }
            if (temp.a == temp.c)   //a, b之间我选择了a, b数组里面的a的位置就确定了
            {
                int id = bb[temp.a].id; //b数组里面被影响对应的id
                if (c[id])  //说明题目已经给你确定了
                {
                    continue;
                }
                else    //这个位置是确定的,但是题目没有给你确定
                {
                    c[id] = bb[temp.a].a;
                    bb[temp.a].c = c[id];
                    q.push({bb[temp.a].a, bb[temp.a].b, bb[temp.a].c, bb[temp.a].id});
                }
            }
            else if (temp.b == temp.c)  //a, b之间我选择b, a数组里面的b位置就确定了
            {
                int id = aa[temp.b].id;
                if (c[id])  //说明题目已经给你确定了
                {
                    continue;
                }
                else
                {
                    c[id] = aa[temp.b].b;   //注意这里有更新
                    aa[temp.b].c = c[id];
                    q.push({aa[temp.b].a, aa[temp.b].b, aa[temp.b].c, aa[temp.b].id});
                }
            }
        }
 
        //下面就是讨论剩下的没标记的,可以构成多少个环,因为如果是环的话,一个变,整体变,每个环的贡献都 * 2
        //数字看环的个数并查集考虑
        int count = 0;
        for (int i = 1; i <= n; ++i)
        {
            if (c[i])   //c[i]的位置是确定的
            {
                continue;
            }
            else
            {
                int fax = find(a[i]);
                int fay = find(b[i]);
                if (fax == fay) //他们的祖先已经相等了,但是还是要给他们连边,那就构成了环
                {
                    ++count;
                }
                else
                {
                    fa[fax] = fay;
                }
            }
        }
        cout << quick_pow(2ll, count) << endl;  //最后的答案就是并查集环的个数的2的count次,因为每次的贡献都 * 2
        
    }
	return 0;
}
/*
1
8
1 6 4 7 2 3 8 5
3 2 8 1 4 5 6 7
1 0 0 7 0 3 0 5
*/

标签:int,ll,位置,RBS,base,result,Recover,MOD
来源: https://www.cnblogs.com/jumo-xiao/p/16507909.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有