bzoj1485 HNOI2009 有趣的數列

2022-05-22 20:51:11 字數 1104 閱讀 4391

思路:首先限制數很多,逐步來考慮,限制一很容易滿足,考慮限制二,也就是讓奇數字和偶數字上的數遞增,限制三就是讓奇數字上的數小於奇數字加一對應的偶數字上的數,那麼我們可以把形成序列的過程看成加數的過程,從小到大逐步加(這顯然滿足限制一),然後加數的條件一是從小到大依次放奇數字或偶數字,因此也滿足限制二,然後無論何時奇數字上的數一定要大於等於偶數字上的數,這樣也滿足了限制三,那麼問題就轉化成了按照如上條件放數的方案數,聯絡第二個條件,也就是無論何時奇數字上的數一定要大於等於偶數字上的數,聯想到了什麼?沒錯,就是棧,進棧次數一定要大於等於出棧次數,不妨把放在奇數字上看成進棧,放在偶數字上看成出棧,這樣就是求乙個出棧的序列,也就是catalan數列。

然後p不一定是素數,也就是不能求逆元,那麼就可以分解質因數,乘乙個數相當於把乙個數的所有質因數乘一遍,就可以用乙個陣列記錄一下所有數被乘了多少遍,那麼乘就是加一,除就是減一,然後n最大為1e6,暴力求每個數的質因數是n*sqrt(n)的,顯然會t(然而我還傻乎乎地交了一遍,看到跑了那麼久猛然醒悟過來。。。。。),於是就可以線篩統計出每個數的最小質因數,然後求每個數的所有質因數時每次除以最小質因數就好了,然後最小質因數一定》=2,因此這樣是nlogn的(而且一點也不嚴格),然後就可以飛快跑過本題。

#includeusing namespace std;

#define maxn 3000005

int n,p,ans=1,tot;

int f[maxn],prime[maxn],pos[maxn];

bool isprime[maxn];

int read()

void change(int x,int val)

int power(int a,int k,int p)

int main()

}for (int i=2*n;i>n+1;i--) change(i,1);

for (int i=1;i<=n;i++) change(i,-1);

for (int i=1;i<=tot;i++) if (f[prime[i]]) ans=1ll*ans*power(prime[i],f[prime[i]],p)%p;

printf("%d\n",ans);

return 0;

}

BZOJ 1485 HNOI2009 有趣的數列

bzoj 1485 hnoi2009 有趣的數列 卡特蘭數 我們稱乙個長度為2n的數列是有趣的,當且僅當該數列滿足以下三個條件 1 它是從1到2n共2n個整數的乙個排列 2 所有的奇數項滿足a1 3 2n 1,所有的偶數項滿足a2 4 2n 3 任意相鄰的兩項a2i 1與a2i 1 i n 滿足奇數...

BZOJ1485 HNOI2009 有趣的數列

題解 考慮按順序從小到大,加入數字,將加入奇數字置看作入棧,加入偶數字置看作出棧。為什麼可以?考慮我們要保證相鄰奇數小於偶數,所以必須先填上乙個奇數的位置才能填偶數的位置,既時刻保證奇數 偶數,最終奇數等於偶數。觀察到這個性質,我們應該聯想到卡特蘭數了,套用公式求解。本題模數可能為合數,不一定存在逆...

狡猾的商人 bzoj1202,HNOI2005

ac通道 分析 因為每月的總收入可以為正,也可以為負,所以要比較兩個區間是否相符,當且僅當它們邊界都相同時才能比較。我們設w i 表示第1 i個月的總收入與第1 fa i 1 個月的總收入之差,及第fa i i個月的總收入。如圖。若i 1,j在同乙個集合中,則第i j個月的總收入為w j w i 1...