【清華集訓2017模擬】Catalan
Description
求
n<=10^18,T<=10
Solution
這麼大的組合數取模啊。。。。以前真沒見過
首先我們知道
根據套路我們只需要把n!寫成5^e*f的形式,然後就可以用逆元直接算了
但是如何計算?
首先我們把所有5的倍數提取出來,那麼有
這樣就可以遞迴下去計算了
那麼如何處理剩餘的部分?
我們在處理乘法的時候忽略5的倍數,設
假如我們把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」無限之環
【題目連結】 【思路要點】 先說這道題的正解: 將棋盤看做一張二分圖,每一條邊拆成兩個點,分別屬於二分圖的一邊。 我們需要做一件類似於匹配的事情,同一條邊的兩側或是都沒有管道,或是都有管道。 通過合適的建邊我們能夠用最小費用最大流來解決本題。 時間複雜度