我是靠谱客的博主 碧蓝烤鸡,最近开发中收集的这篇文章主要介绍DTOJ Begin4028&DTOJ3603 table题目题解注意事项代码,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

DTOJ Begin4028&DTOJ3603 table

  • 题目
    • 题目描述
    • 输入格式
    • 输出格式
    • 样例
      • 样例输入 1
      • 样例输出 1
      • 样例输入 2
      • 样例输出 2
    • 数据范围与提示
  • 题解
    • 40分算法
    • AC算法
  • 注意事项
  • 代码

题目

题目描述

C 酱有一个 m × n m times n m×n的数表,行与列的编号都从 1 1 1开始。令 f i , j f_{i,j} fi,j表示表格第 i i i行第 j j j列内的数,那么对于表格的第 i ( i > 1 ) i(i>1) i(i>1)行有

{ f i , 1 = a × f i − 1 , 1 f i , j = a × f i − 1 , j + b × f i − 1 , j − 1 begin{cases}f_{i,1}=a times f_{i-1,1} \ f_{i,j}=atimes f_{i-1,j}+btimes f_{i-1,j-1}end{cases} {fi,1=a×fi1,1fi,j=a×fi1,j+b×fi1,j1

然而 C 酱已经把表格中的数忘得差不多了,他现在只记得第 p p p行的数。他希望你能够帮忙还原出部分位置的数值。

输入格式

输入第一行为 6 6 6个整数 m , n , a , b , p , q m,n,a,b,p,q m,n,a,b,p,q,其中 q q q表示询问的个数。

接下来一行共 n n n个整数,依次表示 f p , 1 , f p , 2 , ⋯   , f p , n f_{p,1},f_{p,2},cdots,f_{p,n} fp,1,fp,2,,fp,n

接下来 q q q行,每行两个整数 x , y x,y x,y,表示 C 酱询问你$f_{x,y}¥的数值。

输出格式

输出共 q q q行,依次表示每个询问的答案在模 998244353 998244353 998244353意义下的取值。

即设答案可以表示为分式 a b frac{a}{b} ba ,则输出整数 x x x使得 b × x ≡ a ( m o d 998244353 ) b times x equiv a pmod {998244353} b×xa(mod998244353) 0 ⩽ x < 998244353 0 leqslant x < 998244353 0x<998244353。可以证明这样的整数 x x x是唯一的。

样例

样例输入 1

5 4 1 1 3 5
1 0 0 0
5 2
3 1
1 2
2 3
4 3

样例输出 1

2
1
998244351
1
0

样例输入 2

10 5 233 2333 6 4
9 3 1 0 10
1 5
10 2
5 3
8 1

样例输出 2

110343631
118211750
770559638
488601

数据范围与提示

测试点编号 n n n m m m a , b a,b a,b p p p
1 , 2 1,2 1,2 ⩽ 100 leqslant 100 100 ⩽ 1 0 5 leqslant 10^5 105 p = 1 p=1 p=1
3 , 4 3,4 3,4 ⩽ 100 leqslant 100 100 ⩽ 1 0 5 leqslant 10^5 105 a = b = 1 a=b=1 a=b=1
5 , 6 , 7 , 8 5,6,7,8 5,6,7,8 ⩽ 100 leqslant 100 100 ⩽ 1 0 5 leqslant 10^5 105
9 , 10 , 11 , 12 9,10,11,12 9,10,11,12 ⩽ 1 0 5 leqslant 10^5 105 ⩽ 1 0 5 leqslant 10^5 105 p = 1 p=1 p=1
13 , 14 , 15 , 16 13,14,15,16 13,14,15,16 ⩽ 1 0 5 leqslant 10^5 105 ⩽ 1 0 5 leqslant 10^5 105 p = m p=m p=m
17 , 18 , 19 , 20 17,18,19,20 17,18,19,20 ⩽ 1 0 5 leqslant 10^5 105 ⩽ 1 0 7 leqslant 10^7 107

对于 100 % 100% 100%的数据,保证 1 ⩽ q ⩽ 100 , 1 ⩽ x , p ⩽ m , 1 ⩽ y ⩽ n , 1 ⩽ a , b < 998244353 , 0 ⩽ f i , j < 998244353 1 leqslant q leqslant 100 , 1 leqslant x , p leqslant m , 1 leqslant y leqslant n , 1 leqslant a,b < 998244353,0 leqslant f_{i,j} < 998244353 1q100,1x,pm,1yn,1a,b<998244353,0fi,j<998244353

题解

40分算法

暴力把所有格子算出来
代码:

#include<iostream>
using namespace std;
int m,n,a,b,p,q;
long long ny,f[100010][110],MOD=998244353;
long long POW(long long a,long long b)
{
	long long ans=1;
	for(;b;b>>=1){
		if(b&1) ans=(ans*a)%MOD;
		a=(a*a)%MOD;
	}
	return ans;
}
int main()
{
	cin>>m>>n>>a>>b>>p>>q;
	ny=POW(a,MOD-2);
	for(int i=1;i<=n;i++) cin>>f[p][i];
	for(int i=p+1;i<=m;i++) for(int j=1;j<=n;j++) f[i][j]=((a*f[i-1][j])%MOD+(b*f[i-1][j-1])%MOD)%MOD;
	for(int i=p-1;i>0;i--) for(int j=1;j<=n;j++) f[i][j]=(((f[i+1][j]-(b*f[i][j-1])%MOD)%MOD*ny)%MOD+MOD)%MOD;
	for(int i=1,x,y;i<=q;i++) cin>>x>>y,cout<<f[x][y]<<endl;
	return 0;
}

AC算法

我们先分类讨论,在第 p p p行下和在第 p p p行上
若在第 p p p行下,我们可以由上面的两个点得出下面一个点

由题目可知, f i , j = a × f i − 1 , j + b × f i − 1 , j − 1 f_{i,j}=atimes f_{i-1,j}+btimes f_{i-1,j-1} fi,j=a×fi1,j+b×fi1,j1

所以,我们考虑第 p p p行中,要求的点 ( x , y ) (x,y) (x,y)左侧的点 ( p , i ) (p,i) (p,i)(即 i ⩽ y ileqslant y iy),它对 ( x , y ) (x,y) (x,y)的贡献就是 ( p , i ) (p,i) (p,i) ( x , y ) (x,y) (x,y)的路径条数(只能向右下或向下走) × a ⋯ × b ⋯ times a^{cdots}times b^{cdots} ×a×b

我们只需要求 ( p , i ) (p,i) (p,i) ( x , y ) (x,y) (x,y)的路径条数和 a a a b b b的次数

假设 n = x − p , m = y − i n=x-p,m=y-i n=xp,m=yi,那么,我们可以知道我们一共需要走 n n n步,向右下走 m m m步,所以路径数就是 C n m C^m_n Cnm

所以最终的结果就是: C n m × a n − m × b m C^m_ntimes a^{n-m}times b^{m} Cnm×anm×bm

所以我们还能得到一个范围: n ⩾ m ngeqslant m nm
终于,我们解决了 ( x , y ) (x,y) (x,y)在在 p p p行下,即 x > p x>p x>p的情况,接下来,我们讨论一下 x < p x<p x<p的情况

同样,我们可以通过下面的和他左边的点得到这个位置的值, f i , j = f i + 1 , j a − b × f i , j − 1 a f_{i,j}=frac{f_{i+1,j}}{a}-frac{btimes f_{i,j-1}}{a} fi,j=afi+1,jab×fi,j1,那么,问题就变成考虑第 p p p行中,要求的点 ( x , y ) (x,y) (x,y)左侧的点 ( p , i ) (p,i) (p,i)(即 i ⩽ y ileqslant y iy),它对 ( x , y ) (x,y) (x,y)的贡献就是 ( p , i ) (p,i) (p,i) ( x , y ) (x,y) (x,y)的路径条数(只能向上或右走) × a ⋯ × ( − b a ) ⋯ times a^{cdots}times left(-frac{b}{a}right)^{cdots} ×a×(ab)

同样假设 n = p − x , m = y − i n=p-x,m=y-i n=px,m=yi,但是,不一样的地方在于第一步必须向上走!所以,我们可以知道去掉先向上走的一步后,一共需要走 n + m − 1 n+m-1 n+m1步,向右走 m m m步,所以路径数就是 C n + m − 1 m C^m_{n+m-1} Cn+m1m

所以最终的结果就是: C n + m − 1 m × a n × ( − b a ) m C^m_{n+m-1}times a^{n}times left(-frac{b}{a}right)^{m} Cn+m1m×an×(ab)m

注意事项

  1. 取模
  2. 阶乘的逆元可以反着算, i n v j c i = i n v j c i + 1 ∗ ( i + 1 ) invjc_i=invjc_{i+1}*(i+1) invjci=invjci+1(i+1),这样就避免了多次的 p o w pow pow
  3. 提前保存 a a a的逆元
  4. 提前保存 − b a -frac{b}{a} ab的次方,避免计算 − 1 y − i -1^{y-i} 1yi
  5. x < p x<p x<p的情况中,是 C n + m − 1 m C^m_{n+m-1} Cn+m1m

代码

#include<iostream>
using namespace std;
int n,m,p,q;
long long a,b,MOD=998244353,f[10100010],jc[10100010],cj[10100010],pa[10100010],pb[10100010],ap[10100010],bp[10100010];
/*
f:第p行的值
jc:阶乘
cj:阶乘的逆元
pa:a的次方
pb:b的次方
ap:pa的逆元
bp:-b/a的次方 
*/ 
long long POW(long long a,long long b)//快速幂 
{
	long long ans=1;
	for(;b;b>>=1){
		if(b&1) ans=(ans*a)%MOD;
		a=(a*a)%MOD;
	}
	return ans;
}
long long C(int x,int y)//求组合数 
{
    if(x<0||y<0||y>x) return 0;
    return jc[x]*cj[y]%MOD*cj[x-y]%MOD;
}
int main()
{
    cin>>m>>n>>a>>b>>p>>q;
    jc[0]=pa[0]=pb[0]=ap[0]=bp[0]=1;
    for(int i=1;i<=10100000;i++) jc[i]=jc[i-1]*i%MOD;//暴力求阶乘 
    cj[10100000]=POW(jc[10100000],MOD-2);
    for(int i=10099999;i>=0;i--) cj[i]=cj[i+1]*(i+1)%MOD;//反向求阶乘的逆元 
    long long na=POW(a,MOD-2),nb=MOD-(b*na%MOD);
    for(int i=1;i<=10100000;i++) pa[i]=pa[i-1]*a%MOD,pb[i]=pb[i-1]*b%MOD,ap[i]=ap[i-1]*na%MOD,bp[i]=bp[i-1]*nb%MOD; 
    for(int i=1;i<=n;i++) cin>>f[i];
    for(int i=1,x,y;i<=q;i++){
        cin>>x>>y;
        if(x==p){cout<<f[y]<<endl;continue;}
        long long ans=0;
        if(x>p){for(int j=1;j<=y;j++) if(y-j<=x-p) ans=(ans+f[j]*C(x-p,y-j)%MOD*pa[x-y-p+j]%MOD*pb[y-j]%MOD)%MOD;}
		//括号很重要!不能删除 
		else for(int j=1;j<=y;j++) ans=(ans+f[j]*C(y-x+p-j-1,y-j)%MOD*ap[p-x]%MOD*bp[y-j]%MOD)%MOD;
		//分类讨论 
        cout<<ans<<endl;
    }
}

最后

以上就是碧蓝烤鸡为你收集整理的DTOJ Begin4028&DTOJ3603 table题目题解注意事项代码的全部内容,希望文章能够帮你解决DTOJ Begin4028&DTOJ3603 table题目题解注意事项代码所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(39)

评论列表共有 0 条评论

立即
投稿
返回
顶部