1. 程式人生 > >JZOJ-senior-5946. 【NOIP2018模擬11.02】時空幻境(braid)

JZOJ-senior-5946. 【NOIP2018模擬11.02】時空幻境(braid)

Time Limits: 1000 ms Memory Limits: 524288 KB

Description

Tim擁有控制時間的能力。他學會了BFS後,出了一道題:求出一張無向圖中連通塊的個數。他想請你做出這道題來

Input

在這裡插入圖片描述

Output

T行,每行一個數,表示聯通塊的個數。

Sample Input

Sample Input1 1 998244353 4 1 3

Sample Input2 5 998244353 9088 709393585 591328017 998244353 8408 476368048 122172238 998244353 217 922587543 10 998244353 2948991 40846641 7 998244353 2692315 542601916 5

Sample Output

Sample Output1 998244349

樣例解釋 邊為{1,3},{9,27},{81,243},{729,2187} ,所以共有998244349個聯通塊。

Sample Output2 998235265 998235945 998244136 995295362 995552038

Data Constraint

對所有資料,n=998244353, 1<=m,k,x<998244353, 1<=T<=10000 在這裡插入圖片描述

Solution

這題和bfs沒有任何關係?! 觀察連邊的編號,a1=xan=xkn1a_1=x,a_n=x*k^{n-1}

根據抽屜原理,必然是會有迴圈節出現的 考慮迴圈節長度 lenlen 的奇偶性 奇數:必然會形成一個環,聯通塊個數為 n(len1)n-(len-1) 偶數:點之間僅兩兩連邊 n(len/2)n-(len/2) 所以我們就要求出最小正整數 aaka1(modP)k^a\equiv1(mod P) aa 一定是 P1P-1 的約數,而 P1P-1 又是固定的數,所以預處理它的約數,96個 對於每次詢問,從小到大列舉約數,找到第一個符合的即可

Code

#include<algorithm>
#include<cstdio> #define fo(i,a,b) for(int i=a;i<=b;++i) #define fd(i,a,b) for(int i=a;i>=b;--i) #define ll long long using namespace std; const int M=31600,N=998244353; int T,n,m,x,k,tot; int g[3],f[3],a[100]; int ksm(int a,int b,int MO) { int s=1; for(;b;a=(ll)a*(ll)a%MO,b>>=1) if(b&1) s=(ll)s*(ll)a%MO; return s; } void get(int t,int y) { if(t>2) {a[++tot]=y; return;} fo(i,0,f[t]) { int z=1; fo(j,1,i) z*=g[t]; get(t+1,y*z); } } int main() { freopen("braid.in","r",stdin); freopen("braid.out","w",stdout); g[0]=2,g[1]=7,g[2]=17; f[0]=23,f[1]=1,f[2]=1; get(0,1); sort(a+1,a+1+tot); scanf("%d",&T); while(T--) { scanf("%d%d%d%d",&n,&m,&x,&k); int e=0,ans; fo(i,1,tot) if(ksm(k,a[i],n)==1) {e=a[i]; break;} if(e&1) ans=n-min(m,e-1); else ans=n-min(m,e/2); printf("%d\n",ans); } }