題意:
給一個(gè)序列,序列值代表對(duì)應(yīng)下標(biāo)下一秒硬幣要移動(dòng)到的下標(biāo),再給一個(gè)相同01序列,1代表在這個(gè)位置下一秒硬幣翻轉(zhuǎn)。問需要修改幾次這兩個(gè)序列使得每一枚硬幣經(jīng)過若干秒后能以正面和反面的姿態(tài)都經(jīng)過過每一個(gè)點(diǎn)。
解題思路:
之所以需要修改是硬幣的移動(dòng)位置會(huì)形成循環(huán),而這個(gè)循環(huán)有可能不是全局的,是分成幾堆硬幣內(nèi)部循環(huán),我們需要找出這樣硬幣的堆數(shù),如果堆數(shù)是一那么正好不用改,如果大于一就需要把這幾堆硬幣串聯(lián)再一起,需要的修改數(shù)量就是堆數(shù)。
而翻轉(zhuǎn)的序列就很好考慮了,我們只考慮一枚硬幣,這枚硬幣經(jīng)過其它所以點(diǎn)回到原來點(diǎn)后,如果翻轉(zhuǎn)次數(shù)是偶數(shù),那么回來時(shí)的狀態(tài)和出發(fā)時(shí)的狀態(tài)是一樣的,這樣就會(huì)循環(huán)下去,那么肯定是不可以正反兩面都經(jīng)過每一個(gè)點(diǎn)的,所以要求翻轉(zhuǎn)的次數(shù)是奇數(shù)。
代碼:
#include <bits/stdc++.h>using namespace std;const int maxn=2e5;int add[maxn];bool rev[maxn];bool vis[maxn];int main(){ int n; scanf("%d", &n); int i; for(i=1; i<=n; i++)scanf("%d", &add[i]); int cir=0; for(i=1; i<=n; i++) { if(vis[i])continue; cir++; int t=i; do { vis[t]=1; t=add[t]; }while(i!=t); } int odd=0; for(i=1; i<=n; i++){scanf("%d", &rev[i]);if(rev[i])odd++;} int ans=0;// PRintf("%d/n", ans); if(odd%2==0)ans++; printf("%d/n", ans+(cir>1?cir:0)); return 0;}
新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注