题解:洛谷 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) 
*/
posted @ 2025-08-13 19:54  wwwidk1234  阅读(12)  评论(0)    收藏  举报