https://www.luogu.com.cn/problem/P11362
参考这篇题解做的,也是参考它写的。
我们令能放下 x 个二元限制,两端有一元限制的区间的方案数是 f(x) 。
我们考虑限制的第一个数字是左端点的值,那么就有 v 种取法(因为 a 固定, b 有 v 种取法),然后还剩下 f(x-1) ,用乘法原理就是 v\times f(x-1) 。
我们考虑不是的情况,就是限制第一个数有 v-1 种第二个有 v 种,其他随便取,那么就是:
v\times(v-1)\times v^{2x-2}
=v^{2x-1}\times(v-1)
=v^{2x-1}\times v-v^{2x-1}
=v^{2x}-v^{2x-1}
那么 f(x)=v^{2x}-v^{2x-1}+v\times f(x-1) 。
其中边界条件是 f(1)=v^2-v+1
我们把 f(x-1) 展开:
f(x)=v^{2x}-v^{2x-1}+v\times((v^{2x-2}-v^{2x-3})\times v\times f(x-2))
f(x)=v^{2x}-v^{2x-1}+v^{2x-1}-v^{2x-2}+v^2\times f(x-2)
f(x)=v^{2x}-v^{2x-2}+v^2\times f(x-2)
再展开:
f(x)=v^{2x}-v^{2x-2}+v^2\times (v^{2x-4}-v^{2x-5}+v\times f(x-3))
f(x)=v^{2x}-v^{2x-2}+v^{2x-2}-v^{2x-3}+v^3\times f(x-3)
f(x)=v^{2x}-v^{2x-3}+v^3\times f(x-3)
你发现规律了吗,我们不断展开就是: f(x)=v^{2x}-v^{2x-y}+v^y\times f(x-y)
接下来我们把 y=x-1 代录算式:
f(x)=v^{2x}-v^{x+1}+v^{x-1}\times f(1)
f(x)=v^{2x}-v^{x+1}+v^{x-1}\times(v^2-v+1)
f(x)=v^{2x}-v^{x+1}+v^{x+1}-v^x+v^{x-1}
f(x)=v^{2x}-v^{x}+v^{x-1}
我们先按 c_i 排序。
答案就是就是对于所有一原限制得出的 \displaystyle\prod_{i=2}^{n}f(c_i-c_{i-1})\times v^{2\times(c_1-1)}\times v^{2\times(n-c_m)} 。解释一下后面的,是开头的还没有到 c_1 的那一个区间和$c_m$ 没有到结尾的那一段区间。
还有一些细节:
1.如果前后两 c_i 相同但是 d_i 不同,那么无解,若 d_i 想同则跳过不能重复计算。
2. 记得随时取模,计算的时候有减法,要取模后加上模数再取模。
核心代码:
for(int i=2;i<=m;++i)
{
if(a[i-1].x==a[i].x&&a[i-1].y!=a[i].y)//如果出现位置相同但是值不同,那么无解
{
flag=0;
cout<<0<<endl;
break;
}
if(a[i-1].x==a[i].x) continue;//要去重
ans=ans*calc(a[i].x-a[i-1].x)%Mod;//处理中间
}
if(!flag) continue;
ans=ans*qpow(v,2*(a[1].x-1))%Mod;//处理开头
ans=ans*qpow(v,2*(n-a[m].x))%Mod;//处理结尾
cout<<ans<<endl;