题解:洛谷 P13561 「WWOI R1」WsW 的笔
拿到题目之后,思考如何直接一步到位算出方案数有点困难,所以考虑将一件事拆开来做。
首先对于两支编号分别为 \(x,y\) 的笔,若 \((x,y)\) 满足 \(\dfrac{x}{y}=k\) 那么这两支笔就只有一种方案(\(x\) 送出 \(y\) 留下或 \(x\) 留下 \(y\) 送出)。下文把这种 \((x,y)\) 叫做“有限制的数对”。
在 \(a \sim b\) 范围内,有限制的数对有这些:\((a,ak),(a+1,(a+1)k),(a+2,(a+2)k),\cdots,\left(\dfrac{b}{k},b\right)\)。有限制的数对的个数 \(s\) 就是 \(a \sim \dfrac b k\) 中数的个数,即 \(s=\lfloor \dfrac b k \rfloor -a+1\)。每一个有限制的数对都有两种方案,所以这些数对的方案一共有 \(2^s\) 种。
剩下还有 \(b-a+1-2s\) 支笔(不是数对),每一支笔都有送出与不送两种选择方案,所以剩下这些笔的方案数就是 \(2^{b-a+1-2s}\)。
注意到:选择笔的过程分成了两步走:先选有限制的数对再选剩下的笔,满足乘法原理,故最终答案为上面两步方案数的乘积,即 \(2^s \times 2^{b-a+1-2s}\)。
提醒:如果你 TLE 了那就检查一下是不是算出了 \(s<0\) 的情况导致快速幂爆炸了。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
constexpr int N=-1;
constexpr int mod=1e9+7;
inline ll ksm(ll a,ll b)
{
ll s=1;
while(b)
{
if(b&1) s=s*a%mod;
a=a*a%mod;
b>>=1;
}
return s;
}
int main()
{
// freopen("neuvillette.in","r",stdin);
// freopen("neuvillette.out","w",stdout);
int T;
cin>>T;
ll a,b,k,s;
while(T--)
{
cin>>k>>a>>b;
s=ll(b/k)-a+1; //有限制的数对有多少个
if(s<0) s=0;
cout<<ksm(2,b-a+1-2*s)*ksm(2,s)%mod<<'\n';
}
return 0;
}
/*
思路:
总方案数:2^(b-a+1)
若(x,y)满足x/y=k那么只有一种方案(x送出,y留下)或(x留下,y送出)
有限制的数对:(a,ak),(a+1,(a+1)k),(a+2,(a+2)k),...,(b/k,b)“每一个数对”都只有2种方案
设这些数对的个数为s那么这些有限制的数对合法方案数就是2^s
s为满足(a+i-1)<=b/k的最大的i
s=int(b/k)-a+1
没限制的“数”(不是数对)有b-a+1-2s个,每一个数有2种方案(送或者不送),方案数2^(b-a+1-2s)
*/

浙公网安备 33010602011771号