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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

jzoj6311-Mobitel【dp,整除分块】

發布時間:2023/12/3 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 jzoj6311-Mobitel【dp,整除分块】 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

正題


題目大意

n?mn*mn?m的矩陣,求有多少條路徑的乘積不小于SSS


解題思路

我們用總路徑數減去乘積小于SSS的路徑數

我們很容易想到用fi,j,kf_{i,j,k}fi,j,k?表示到(i,j)(i,j)(i,j)這個點,然后乘積之和為kkkdpdpdp。但是時間復雜度O(nmS)O(nmS)O(nmS)顯然難以勝任本題。

我們考慮將S?1S-1S?1整除分塊,用fi,j,kf_{i,j,k}fi,j,k?表示(i,j)(i,j)(i,j)這個點時,再乘上一個大于等于kkk的數就會大于等于SSS

然后我們可以得到動態轉移方程
fi,j,k=fi?1,j,z+fi,j?1,z(z=S?1?S?1k??ai,j)f_{i,j,k}=f_{i-1,j,z}+f_{i,j-1,z}(z=\frac{S-1}{\lfloor\frac{S-1}{k}\rfloor*a_{i,j}})fi,j,k?=fi?1,j,z?+fi,j?1,z?(z=?kS?1???ai,j?S?1?)

然后kkk只有2?S2*\sqrt S2?S?,所以時間復雜度O(nmS)O(nm\sqrt S)O(nmS?)


codecodecode

#include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; const int XJQ=1e9+7,N=310; int n,m,s,t,a[N][N],f[2][N][5000],ans,num[5000],v[1100000],c[N][N],cnt; int main() {freopen("mobitel.in","r",stdin);freopen("mobitel.out","w",stdout);scanf("%d%d%d",&n,&m,&s);c[1][0]=1;s--;for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)c[i][j]=(c[i][j-1]+c[i-1][j])%XJQ;for(int i=1,k;i<=s;i=k+1){k=s/(s/i);num[++cnt]=s/i;v[num[cnt]]=cnt;}/*for(int i=s;i>=1;i--)v[i]=v[i]?v[i]:v[i+1];*/for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)scanf("%d",&a[i][j]);f[1][1][v[s/a[1][1]]]=1;for(int i=1;i<=n;i++){memset(f[~i&1],0,sizeof(f[~i&1]));for(int j=1;j<=m;j++)for(int k=1;k<=cnt;k++){int z=num[k];if(!f[i&1][j][k]) continue;if(i<n&&z/a[i+1][j]>0) (f[~i&1][j][v[z/a[i+1][j]]]+=f[i&1][j][k])%=XJQ;if(j<m&&z/a[i][j+1]>0) (f[i&1][j+1][v[z/a[i][j+1]]]+=f[i&1][j][k])%=XJQ;}}for(int k=1;k<=cnt;k++)(ans+=f[n&1][m][k])%=XJQ;printf("%d",(c[n][m]-ans+XJQ)%XJQ); }

總結

以上是生活随笔為你收集整理的jzoj6311-Mobitel【dp,整除分块】的全部內容,希望文章能夠幫你解決所遇到的問題。

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