1. 程式人生 > >【清華集訓2017模擬】Catalan

【清華集訓2017模擬】Catalan

Description

Cnmod3814697265625(518)其中Cn為卡特蘭數第n項
n<=10^18,T<=10

Solution

這麼大的組合數取模啊。。。。以前真沒見過
首先我們知道Ans=Cn2nn+1
根據套路我們只需要把n!寫成5^e*f的形式,然後就可以用逆元直接算了
但是如何計算?
首先我們把所有5的倍數提取出來,那麼有n5個5,並且剩下的數變成了n5!
這樣就可以遞迴下去計算了
那麼如何處理剩餘的部分?
我們在處理乘法的時候忽略5的倍數,設L=mo=59,那麼我們相當於要求

i=0nL1j=0L1(iL+j)
假如我們把i,l當做常數,那麼我們可以發現後面的東西可以寫成(a*i*L+b)的形式
a和b只和L有關,可以預處理
那麼這樣我們處理出a,b,再處理出一個字首積,這個東西就可以O(1)計算了
預處理的複雜度是O(L)的
多出來的那一部分直接處理就好了

但是這樣只能處理n<=mo的情況,n>mo的情況處理不了,怎麼辦呢?
我們發現n>mo的時候我們可以把1~n的數按mo分類,其中每一組在模意義下都是同餘的
這樣直接快速冪計算即可
總複雜度O(L+T log^2N)

Code

#include <cstdio>
#include <cstring>
#include <algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
typedef long long ll;
typedef double db;
const ll mo=3814697265625;
const int L=1953125;
struct note{
    int e;ll f;
    note(int _e=0,ll _f=0) {e=_e;f=_f;}
};
ll f[L][2
],sum[L],n; ll mult(ll a,ll b) { ll a1=a/L,b1=a%L,a2=b/L,b2=b%L; ll tmp=a1*a2%mo*L%mo*L%mo; (tmp+=a1*L%mo*b2%mo)%=mo; (tmp+=a2*L%mo*b1%mo)%=mo; (tmp+=b1*b2%mo)%=mo; return tmp; } ll mi(ll x,ll y) { ll z=1; for(;y;y/=2,x=mult(x,x)) if (y&1) z=mult(z,x); return z; } ll F(ll n) { ll a=n/L,b=n%L,ans=1; if (a) ans=mult(ans,sum[a-1]); ans=mult(ans,(mult(mult(f[b][1],a),L)+f[b][0])%mo); return ans; } note solve(ll n) { if (!n) return note(0,1); note x=solve(n/
(ll)5),ans; if (n>mo) { ll a=n/mo,b=n%mo; ans.f=mult(x.f,mult(mi(F(mo),a),F(b))); } else ans.f=mult(x.f,F(n)); ans.e=(ll)(x.e+n/(ll)5)%18; return ans; } void exgcd(ll a,ll b,ll &x,ll &y) { if (!b) { x=1;y=0; return; } ll xx,yy; exgcd(b,a%b,xx,yy); x=yy;y=xx-a/b*yy; } ll get_inv(ll x) { ll a,b; exgcd(x,mo,a,b); return ((a%=mo)+=mo)%=mo; } int main() { freopen("catalan.in","r",stdin); freopen("catalan.out","w",stdout); f[0][0]=1; fo(i,1,L-1) { if (!(i%5)) { f[i][0]=f[i-1][0]; f[i][1]=f[i-1][1]; continue; } f[i][0]=mult(f[i-1][0],(ll)i); f[i][1]=(f[i-1][0]+mult(f[i-1][1],(ll)i))%mo; } sum[0]=f[L-1][0]; fo(i,1,L-1) sum[i]=mult(sum[i-1],(mult(mult(f[L-1][1],(ll)i),(ll)L)+f[L-1][0])%mo); int ty; for(scanf("%d",&ty);ty;ty--) { scanf("%lld",&n); note a=solve(2*n); note b=solve(n); (a.e+=18-2*b.e%18)%=18; ll ni=get_inv(b.f); a.f=mult(a.f,mult(ni,ni)); ll nn=n+1; for(;!(nn%5);nn/=5) (a.e+=17)%=18; a.f=mult(a.f,get_inv(nn)); ll c=mult(a.f,mi(5,a.e)); printf("%lld\n",c); } }

相關推薦

清華集訓2017模擬Catalan

Description 求Cnmod3814697265625(518)其中Cn為卡特蘭數第n項 n<=10^18,T<=10 Solution 這麼大的組合數取模啊。。。。以前真沒見過 首先我們知道Ans=Cn2nn+1 根據套路我們只

清華集訓2017模擬12.10迴文串(迴文樹+樹鏈剖分)

Description: NYG 很喜歡研究迴文串問題,有一天他想到了這樣一個問題: 給出一個字串 S,現在有 4 種操作: • addl c :在當前字串的左端加入字元 c; • addr c :在當前字串的右端加入字元 c; • transl l

JZOJ 5490. 清華集訓2017模擬11.28圖染色

Description Input 第一行包括兩個整數N,M。 接下來M行每行兩個整數u,v,代表存在一條裡連線 u,v的無向邊。可能存在重邊自環。 Output 降序輸出所有不為0的F(i) 。保留6位小數輸出。 Sample Inpu

UOJ#340清華集訓2017小 Y 和恐怖的奴隸主(矩陣快速冪,動態規劃)

【UOJ#340】【清華集訓2017】小 Y 和恐怖的奴隸主(矩陣快速冪,動態規劃) 題面 UOJ 洛谷 題解 考慮如何暴力\(dp\)。 設\(f[i][a][b][c]\)表示當前到了第\(i\)次攻擊,還剩下的\(1,2,3\)血的奴隸主個數為\(a,b,c\)的概率,每次考慮打到了哪裡,做一個

清華集訓 2017無限之環(費用流)

題目連結 題解 費用流神題。 對於每一個方格延伸出去的每一根水管,有且僅有一個其他方格延伸出的水管與之相連,這樣就不會漏水。即:每根水管的容量為11,且必須滿流。 然而即使產生了最優情況,整個管網也不一定是一整個聯通塊,而可能被分成若干塊。因此,

LOJ#2320. 「清華集訓 2017」生成樹計數

rac res 然而 除了 加法 wap OS 代碼 reg 題解 我,理解題解,用了一天 我,卡常數,又用了一天 到了最後,我才發現,我有個加法取模,寫的是while(c >= MOD) c -= MOD 我把while改成if,時間,少了 六倍。 六倍。 六倍!!

LOJ2322清華集訓 2017」Hello world!

【題目連結】 點選開啟連結 【思路要點】 一個 1

LOJ2328清華集訓 2017」避難所

【題目連結】 點選開啟連結 【思路要點】 令 x

LOJ2326清華集訓 2017」簡單資料結構

【題目連結】 點選開啟連結 【思路要點】 注意到答案是 O

LOJ2323清華集訓 2017」小 Y 和地鐵

【題目連結】 點選開啟連結 【思路要點】 很不錯的腦洞題。 附上官方題解。 時間複雜度 O

LOJ2324清華集訓 2017」小 Y 和二叉樹

【題目連結】 點選開啟連結 【思路要點】 答案的第一位一定是編號最小的度數不為 3

LOJ2329清華集訓 2017」我的生命已如風中殘燭

【題目連結】 點選開啟連結 【思路要點】 一個直觀的思路是模擬該過程,當路上遇到環的時候通過類似取模的手段加速。 注意到每繞一個環

LOJ2331清華集訓 2017」某位歌姬的故事

【題目連結】 點選開啟連結 【思路要點】 注意到若一個位置被兩種音高 a

LOJ2330清華集訓 2017」榕樹之心

【題目連結】 點選開啟連結 【思路要點】 首先,樹是二分圖,只有一側的點可能成為心。 維護每一棵子樹會產生的向下推動的次數可能的最大值

LOJ2327清華集訓 2017」福若格斯

【題目連結】 點選開啟連結 【思路要點】 M

期望+矩陣乘法LOJ2325 [清華集訓 2017] 小 Y 和恐怖的奴隸主

【題目】 原題地址 BOSS \text{BOSS} BOSS初始有一個

loj#2330. 「清華集訓 2017」榕樹之心樹形dp

傳送門 解題思路: 先考慮根是否可行,即步數是否能抵消完。 考慮w[x]w[x]表示xx的子樹內最少的消剩下的點數。 觀察發現,最難消的肯定是sizesize最大的兒子,設為 yy ,而且如果

LOJ#2330. 「清華集訓 2017」榕樹之心 -樹形dp

題解 先考慮根的情況(Subtask3Subtask3)。 根的每個兒子及其構成的子樹之間可以互相抵消。 設rem[i]rem[i]表示以ii為根的子樹最少的不能互相抵消的點數。 那

LOJ2320清華集訓 2017」生成樹計數

【題目連結】【思路要點】連上\(a_i\)的限制,題目要求的實際上是\(\sum_{T}\prod_{i=1}^{N}a_i^{d_i}*d_i^{M}\sum_{i=1}^{N}d_i^{M}\)。我們知道樹的Prufer序列與樹點的度數密切相關,因此考慮使用Prufer序

LOJ2321清華集訓 2017」無限之環

【題目連結】 【思路要點】 先說這道題的正解: 將棋盤看做一張二分圖,每一條邊拆成兩個點,分別屬於二分圖的一邊。 我們需要做一件類似於匹配的事情,同一條邊的兩側或是都沒有管道,或是都有管道。 通過合適的建邊我們能夠用最小費用最大流來解決本題。 時間複雜度