您的位置:首页 > 其它

【组合数学+转化问题】BZOJ4005[JLOI2015]骗我呢

2018-02-01 22:37 218 查看
【题目】

原题地址

求有多少个n行m列的矩阵满足每个数都在[0,m]之间且ai,j<ai,j+1,ai,j<ai−1,j+1,答案模1e9+7

【解题思路】

这道题想了我好久啊,然后去看了一下PoPoQQQ的题解,一脸要膜拜的样子。转化后的模型在QBXT讲过qwq。

首先考虑这个矩阵本身有什么性质,发现如果我们将每个大小关系连一条边,那么每个点至少在一条长度为m的链上,而可供选择的数字大小仅有m+1个,也就是说,一条链上最多只有一条边两点权相差为2,其他差值都为1

考虑转化问题(qwq我不会转化),我们发现实质是是这样一幅图:



求从左下角走到右上角,只能往上或往右走,不碰到两条斜线的方案数。

当然这是n≤m的情况,实际上n>m时也是一样的,我们都构造y=x+1和y=x−(m+2)两条“限制线”即可。

(以下这两条直线称作A和B)

那么接下来考虑如何计算,我们可以尝试用容斥原理,即【全集-跨越第一条的方案-跨越第二条的方案+两条都跨越的方案 】。但是这样最后一种是很难计算的。

下面是另一种转化思路:触碰的情况可能非常复杂 比如ABABBABBBAA啥的,为了避免重复计数我们把相同的都缩掉变成ABABABA这样的串

然后怎么搞呢? 秀操作咯。(接下来的东西我在QBXT是没有认真听的,回来推了好久qwq)

我们令初始点为(n+m+1,n),然后我们做这样的操作:

将当前点沿A翻转,然后把原点到当前点的方案数从答案中减去;

将当前点(注意此时已经翻转过了)沿B翻转,然后把原点到当前点的方案数从答案中加上;

反复如此直到某一坐标<0 此时无论如何进行下去方案数都是0了

这样做相当于把以A和AB为后缀的方案删除,然后把以BA和BAB为后缀的方案加回去,然后把以ABA和ABAB为后缀的方案删除……

最后我删除的就是以A为前缀的所有方案!

然后我们再恢复,先沿B翻转再做一次,就删掉了以B为前缀的所有方案

这样做时间复杂度是O(n)的,写起来也很简单。

还有一种转化方式可以看这里

都好神啊。

【参考程序】

#include<bits/stdc++.h>
using namespace std;

typedef long long LL;
const int mod=1e9+7;
const int N=3e6+10;
int n,m,x,y,ans;
int fac
,inv
;

void init()
{
fac[0]=fac[1]=1;
for(int i=2;i<N;++i)
fac[i]=1ll*fac[i-1]*i%mod;
inv[0]=inv[1]=1;
for(int i=2;i<N;++i)
inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod;
for(int i=2;i<N;++i)
inv[i]=1ll*inv[i]*inv[i-1]%mod;
}

int C(int p,int q)
{
if(p<q) return 0;
return 1ll*fac[p]*inv[q]%mod*inv[p-q]%mod;
}

int calc(int p,int q)
{
if(p<0 || q<0)  return 0;
return C(p+q,p);
}

void flip1(int &p,int &q)//flip by y=x+1
{
swap(p,q);
--p;++q;
}

void flip2(int &p,int &q)//flip by y=x-(m+2)
{
swap(p,q);
p+=m+2;q-=m+2;
}

void solve()
{
scanf("%d%d",&n,&m);
ans=calc(n+m+1,n);

x=n+m+1;y=n;
while(x>=0 && y>=0)
{
flip1(x,y);
ans-=calc(x,y);
flip2(x,y);
ans+=calc(x,y);
ans%=mod;
}

x=n+m+1;y=n;
while(x>=0 && y>=0)
{
flip2(x,y);
ans-=calc(x,y);
flip1(x,y);
ans+=calc(x,y);
ans%=mod;
}

ans=(ans+mod)%mod;
printf("%d\n",ans);
}

int main()
{
//  freopen("BZOJ4005.in","r",stdin);
//  freopen("BZOJ4005.out","w",stdout);

init();
solve();

return 0;
}


【总结】

事实上我至今仍然觉得转化十分神奇,虽然是已经大概搞懂了。

这也说明数学方面的思维还有待提高,和一众神犇的差距还很大qwq。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: