7-145 Strings of Red and Blue
题目
给定 \(A\) 个红球,\(B\) 个黑球,现在进行若干次操作,第 \(i\) 次操作可以取走 \(i\) 个相同颜色的球,并将它们放在 \(C\) 串的末尾。
求:有多少种不同的可以得到的 \(C\) 串,要求 \(|C|=N\)。
\(N\le 2\times 10^5,A,B\le 10^5\)。
解题报告
首先先判一下 \(N\) 是否可以表示成 \(\frac{k\times (k+1)}{2}\) 的形式,不可以的话直接输出 \(0\)。
只要中间某一次取的颜色不同,那么 \(C\) 串就是不同的。这就是一个非常简单的 01 背包。可以将红球的个数转化为黑球个数的下界,也就是说黑球取的个数的范围为 \([\max(N-A,0),B]\),只要一开始的背包处理完,然后扫一遍这个范围求答案即可。
复杂度 \(\operatorname{O}(N\sqrt{N})\),其中 \(N\) 是背包容量,\(\sqrt{N}\) 是物品数量。
虽然我考虑过这种不算复杂的计数问题有没有 \(\log\) 及以下的做法,但是没啥思路,反正这题根号可过。
Code
#include <stdio.h>
#include <algorithm>
#define LL long long
using namespace std;
const int Rea=1e5+3;
struct Rin
{
char c;
inline char gc()
{
static char rea[Rea];
static char *head,*tail;
return head==tail&&(tail=(head=rea)+fread(rea,1,Rea,stdin),head==tail)?EOF:*head++;
}
inline Rin&operator >>(int &x)
{
x=0;
bool tag=false;
for(c=gc();c>'9'||c<'0';c=gc())if(c=='-'){c=gc();tag=true;break;}
for(;c>='0'&&c<='9';c=gc())x=(x<<1)+(x<<3)+(c^'0');
if(tag)x=-x;
return *this;
}
}rin;
inline void jh(int &x,int &y){if(x^y)x^=y^=x^=y;return;}
const int N=1e6+3;
const int M=1e9+7;
int n,l,r;
int f[N];
int main()
{
rin>>n>>l>>r;l=max(n-l,0);
int sum=0,ans=0;for(int i=1;sum<n;i++)sum+=i;if(sum!=n){puts("0");return 0;}
sum=0;f[0]=1;
for(int i=1;(sum+=i)<=n;i++){for(int j=sum;j>=i;j--)f[j]=(f[j]+f[j-i])%M;}
for(int i=l;i<=r;i++)ans=(ans+f[i])%M;
printf("%d\n",ans);
return 0;
}
\[\texttt{El Psy Congroo}
\]
$$\texttt{Dirty Deeds Done Dirt Cheap}$$

浙公网安备 33010602011771号