首页 > 其他分享 >CF1863G Swaps 题解

CF1863G Swaps 题解

时间:2024-04-23 14:23:17浏览次数:31  
标签:ch 自环 Swaps int 题解 void CF1863G tag 入边

题目链接

点击打开链接

题目解法

这么牛的题!!!

先套路地建图,连边 \(i\to a_i\)
考虑交换 \(a_i\) 和 \(a_{a_i}\) 的含义,我们把边 \(i\to a_i,\;a_i\to a_{a_i}\) 变成了 \(i\to a_{a_i}\) 和 \(a_i\) 的自环

每次交换的话分析过于复杂,考虑打 \(tag\),我们把所有操作过的 \(i\),在 \(i\to a_i\) 的边上打 \(tag\)
打完 \(tag\) 之后的图,点 \(i\) 会指到哪个点?
如果点 \(i\) 有入边被打上 \(tag\),那么 \(i\) 就是自环;否则一直往后跳边,指到第一条未被打 \(tag\) 的边指向的点就是 \(i\) 会指到的点

从上面的结论不难发现,每个点至多只会有一个入边被打 \(tag\),因为如果一个点有入边被打过 \(tag\) 了,那么这个点就是自环,再打这个点其他入边的 \(tag\) 不会对序列产生影响

看似答案就是 \(\prod\limits_{i=1}^n(in_i+1)\),\(in_i\) 为点 \(i\) 的入度
但是环的情况很特殊
我们可以手画一下单一简单环的情况,发现有 \(n-1\) 的点的入边打上 \(tag\) 之后,整个简单环已经被拆分成 \(n-1\) 的简单环了,也就是说 \(n\) 个点的简单环,至多只能有 \(n-1\) 个点的入边打上 \(tag\)
推广至非简单环的情况,可以手玩一下一个简单环 + 一条入边的情况,发现如果只染非环边和环上的 \(n-2\) 条边,环上的 \(n\) 个点是不会拆分成 \(n\) 个单独的自环的
也就是说,只有染的 \(n-1\) 条边都在环上,才会使环上的每个点都是自环

不难得到答案为 \(\prod\limits_{circle_i}(\prod\limits_{x\in circle_i}(in_x+1)-\sum\limits_{x\in circle}in_x)\prod\limits_{x\notin circle} (in_x+1)\)
时间复杂度 \(O(n)\)

#include <bits/stdc++.h>
#define F(i,x,y) for(int i=(x);i<=(y);i++)
#define DF(i,x,y) for(int i=(x);i>=(y);i--)
#define ms(x,y) memset(x,y,sizeof(x))
#define SZ(x) (int)x.size()-1
#define all(x) x.begin(),x.end()
#define pb push_back
using namespace std;
typedef long long LL;
typedef unsigned long long ull;
typedef pair<int,int> pii;
template<typename T> void chkmax(T &x,T y){ x=max(x,y);}
template<typename T> void chkmin(T &x,T y){ x=min(x,y);}
template<typename T> void read(T &FF){
    FF=0;int RR=1;char ch=getchar();
    for(;!isdigit(ch);ch=getchar()) if(ch=='-') RR=-1;
    for(;isdigit(ch);ch=getchar()) FF=(FF<<1)+(FF<<3)+ch-48;
    FF*=RR;
}
const int N=1000010,P=1e9+7;
int n,ans=1,a[N],in[N];
int col[N],cntcol;
int pas[N],cnt,rv[N];
bool cir[N];
vector<int> G[N];
inline void inc(int &x,int y){ x+=y;if(x>=P) x-=P;}
void dfs(int u){
    col[u]=cntcol,pas[++cnt]=u,rv[u]=cnt;
    for(int v:G[u]){
        if(col[v]==cntcol){
            int val1=1,val2=0;
            F(i,rv[v],cnt) cir[pas[i]]=1,val1=1ll*val1*(in[pas[i]]+1)%P,inc(val2,in[pas[i]]);
            ans=1ll*ans*(val1-val2+P)%P;
        }
        if(!col[v]) dfs(v);
    }
}
int main(){
    read(n);
    F(i,1,n) read(a[i]);
    F(i,1,n) G[i].pb(a[i]),in[a[i]]++;
    F(i,1,n) if(!col[i]) cntcol++,dfs(i);
    F(i,1,n) if(!cir[i]) ans=1ll*ans*(in[i]+1)%P;
    printf("%d\n",ans);
    return 0;
}

标签:ch,自环,Swaps,int,题解,void,CF1863G,tag,入边
From: https://www.cnblogs.com/Farmer-djx/p/18152771

相关文章

  • Numb 题解
    前言五一网课的例题,但是网上没有题解,所以来写一篇,就当攒RP了。题目可以在这里提交。原题是Baekjoon-19083,但是交不了?题目简述给你一个偶数\(n\),求一个二进制数\(x=\overline{a_1a_2\dotsa_n}\),满足:\(x\equiv0\pmod{n}\);\(\foralli\in[1,n]\),\(\overline{......
  • A. Jagged Swaps
    A.JaggedSwaps不是任何暴力,不是任何排序法只需要判断第一个数是不是1,因为最小值是1,而只能从第二个数开始交换第一个数只能是1,不是1则不能构成从小到大有序的序列#include<iostream>#include<algorithm>usingnamespacestd;voidsolve(){intn;cin>>n;......
  • CF1137F Matches Are Not a Child's Play 题解
    题目链接点击打开链接题目解法参考abruce的非\(lct\)的做法\(compare\)操作是搞笑的,可以转化成求\(u,v\)的\(when\)操作一个结论是编号最大的点一定是最晚删的,不妨令编号最大的点为根,则删除顺序一定是从下往上删的先考虑原树上单个点\(u\)的\(when\)怎么求令......
  • wps使用FileDialog(msoFileDialogFolderPicker)问题解决
    在vba里面使用了WithApplication.FileDialog(msoFileDialogFolderPicker),在excel里面多次测试均正常,但在wps里面运行时,发现只有打开文档后第一次运行宏是正确的,之后运行就再取不到选取的单元格,不管怎么选取,.SelectedItems.Count都是0。百度搜索为什么。 找到两个帖子1、 ......
  • 牛客小白月赛91 题解
    A.Bingbong的化学世界签到题意:给你苯环的结构,判断类型。思路:按照区别特判即可。代码:#include<bits/stdc++.h>usingnamespacestd;#definefffirst#definesssecond#definepbpush_back#defineall(u)u.begin(),u.end()#defineendl'\n'#definedebug(x)c......
  • EasyPoi 导出xlsx下拉列表过长问题解决
    问题描述:通过EasyPoi导出Excel带下拉框字段时,下拉框内值超过255时,会报错Stringliteralsinformulascan'tbebiggerthan255charactersASCII解决方案:额外创建sheet页去存储下拉框内数据,然后从这个sheet页中读取下拉框数据存到下拉列表中,最后需将额外创建的sheet隐藏......
  • Two Sided Cards 题解
    前言五一网课的例题,但是网上没有详细的题解(真的连题解都找不到啊),所以来写一篇,就当攒RP了。题目可以在这里提交。原题是TopCoder-10947,但是有了账号也交不了?题目简述有\(n\)张卡片,正面和反面分别组成了\(1\simn\)的排列。现在你需要将这\(n\)张卡片排成一排。卡片......
  • P1168 题解
    P1168中位数-洛谷很巧妙的一个题,自己没想出来。用一个「对顶堆」来维护,即一个大根堆和一个小根堆。保证大根堆的队首\(\le\)小根堆的队首,并使他们的堆中元素的个数尽量相等。操作如下:每次加入一个元素时,如果这个数比大根堆的队首大,就加入小根堆;否则加入大根堆。比较两......
  • P6492 题解
    P6492[COCI2010-2011#6]STEP-洛谷题目大意:维护一段01串,支持单点修改,每次修改后求最长的「\(\texttt{01010101}\dots\)」的长度。下文把「\(\texttt{01010101}\dots\)」称为「合法区间」,\(k\)为区间\([l,r]\)编号,\(lk,rk\)为\([l,r]\)左右子区间编号。考虑用线......
  • atcoder regular 176 (ARC176) A、B题解
     A很容易有一个错误想法,就是行从1~n,列从1~n拿,这样,第三个样例,最后,第7行,第7列,需要都增加两个数,但是(7,7)这个位置只能有一个数。我的做法是优先队列/set队列,每次选择行、列之中当前已经有的数目最少的(这样它们最需要添加),这样能保证,行列需要添加的,不会出现只能选择多个行列一样的......