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} \]

posted @ 2021-02-27 11:02  zjjws  阅读(79)  评论(0)    收藏  举报