日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【bzoj4870】[Shoi2017]组合数问题 dp+快速幂/矩阵乘法

發布時間:2025/3/21 编程问答 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【bzoj4870】[Shoi2017]组合数问题 dp+快速幂/矩阵乘法 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題目描述

輸入

第一行有四個整數 n, p, k, r,所有整數含義見問題描述。 1 ≤ n ≤ 10^9, 0 ≤ r < k ≤ 50, 2 ≤ p ≤ 2^30 ? 1

輸出

一行一個整數代表答案。

樣例輸入

2 10007 2 0

樣例輸出

8


題目大意

問從nk個數中選出若干個,且選出數的數目mod k=r的方案數

題解

dp+快速冪/矩陣乘法

題目描述是騙人的,一個一個加根本不可能加的過來。

關于矩陣乘法的題解可以參考 popoqqq大爺的博客 ,時間復雜度為O(k^3logn),

我的做法是dp+快速冪。

(UPD:后來知道這其實就是循環矩陣乘法)

設 $f[i][j]$ 表示從 $i$ 個數中選出若干個,且選出的數的數目 $\text{mod} k=j$ 的方案數

那么有 $f[i1+i2][j]=\sum((j1+j2)mod?k?=?j)f[i1][j1]?f[i2][j2]$?

這里可能比較難用數學語言表述,但事實上其中的求和符號僅是對于 $j1$ 和 $j2$ ,并不對于 $i1$ 和 $i2$ ,也就是說只要找到任意一組 $i1$ 和 $i2$ ,就可以用 $f[i1]$ 和 $f[i2]$ 推出。

發現這一點類似于乘方,于是我們可以使用快速冪的方法來快速推出f[nk]數組,時間復雜度為O(k^2logn).

注意一下這里k可能等于1,所以初始化時不能簡單地將f[0][1]賦為1,而是將f[0][1%k]加上1。

#include <cstdio> #include <cstring> typedef long long ll; int p , k; struct data {ll f[60];data(){memset(f , 0 , sizeof(f));}data operator*(const data a)const{int i , j;data tmp;for(i = 0 ; i < k ; i ++ )for(j = 0 ; j < k ; j ++ )tmp.f[(i + j) % k] = (tmp.f[(i + j) % k] + f[i] * a.f[j]) % p;return tmp;} }ans; data pow(data x , ll y) {data ans;ans.f[0] = 1;while(y){if(y & 1) ans = ans * x;x = x * x , y >>= 1;}return ans; } int main() {int n , r;scanf("%d%d%d%d" , &n , &p , &k , &r);ans.f[0] ++ , ans.f[1 % k] ++ ;printf("%lld\n" , pow(ans , (ll)n * k).f[r]);return 0; }

轉載于:https://www.cnblogs.com/GXZlegend/p/6855497.html

總結

以上是生活随笔為你收集整理的【bzoj4870】[Shoi2017]组合数问题 dp+快速幂/矩阵乘法的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。