UESTC 电子科大专题训练 数论 G

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UESTC 电子科大专题训练 数论 G相关的知识,希望对你有一定的参考价值。

UESTC 1718

题意:在01串中选出长度为偶数,并且前一半是0,后一半是1的子序列方案数

思路:组合数+范德蒙恒等式 记录每个数前面0的个数pi和后面1的个数nexi(包括本身)遍历到第k个数的时候,如果是0 那么方案数为(因为计算第i位时,前面计算的i-1个答案都不包含这一位,但是第i位计算的答案都包含第i位 所以没有重复)

for(i=0, -> i=min(pi-1,nexi)) C(pi-1,i)*C(nexi,i+1) 可以由 C(l-1,i)=C(l,i+1)-C(l-1,i+1)推得  for(i=0; i<=min(pi,nexi)) C(l,i)*C(r,i) - for(i=0; i<=min(pi-1,nexi)) C(pi-1,i)*C(nexi,i) (∑求和不好写,我就直接for循环表示了)

再由范德蒙恒等式可推得 for(i=0; i<=m) C(m,i)*C(n,i)=C(m+n,m) (其中m<=n)  所以预处理出2e5以内的阶乘和逆元就可以O(n)*O(1)求解了

 AC代码:

#include "iostream"
#include "string.h"
#include "stack"
#include "queue"
#include "string"
#include "vector"
#include "set"
#include "map"
#include "algorithm"
#include "stdio.h"
#include "math.h"
#define ll long long
#define bug(x) cout<<x<<" "<<"UUUUU"<<endl;
#define mem(a) memset(a,0,sizeof(a))
#define mp(x,y) make_pair(x,y)
#define pb(x) push_back(x)
using namespace std;
const long long INF = 1e18+1LL;
const int inf = 1e9+1e8;
const int N=1e5+100;
const ll mod=1e9+7;

ll fac[N<<1], inv[N<<1];
ll fpow(ll a, int b) {ll ans=1; for(;b;a=a*a%mod,b>>=1)if(b&1)ans=ans*a%mod; return ans;}
ll Inv(ll x) {return fpow(x, mod-2);}
ll C(int a, int b){
        if(b==0 || a==b) return 1;
        return fac[a]*inv[b]%mod*inv[a-b]%mod;
}
void Init(){      //求组合数预处理优化,inv[i]表示i的阶乘的逆元
    fac[0]=1;
    for(int i=1; i<(N<<1); ++i) fac[i]=fac[i-1]*i%mod, inv[i]=Inv(fac[i])%mod;
}

char s[N<<1];
int p[N<<1],nex[N<<1];

ll check(int t){
    ll ret=0;
    int m=min(p[t],nex[t]);
    int mm=min(p[t]-1,nex[t]);
    ret=(ret+C(p[t]+nex[t],m))%mod;
    ret=(ret-C(p[t]-1+nex[t],mm))%mod;
    return ret;
}
int main(){
    //ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
    Init();
    scanf("%s",s+1);
    int ls=strlen(s+1),t=0;
    for(int i=1; i<=ls; ++i){
        if(s[i]==0) t++;
        p[i]=t;
    }
    t=0;
    for(int i=ls; i>=1; --i){
        if(s[i]==1) t++;
        nex[i]=t;
    }
    ll ans=0;
    for(int i=1; i<=ls; ++i){
        if(s[i]==0){
            ans=(ans+check(i))%mod;
        }
    }
    ans=(ans+mod)%mod;
    printf("%lld\n",ans);
    return 0;
}

 

以上是关于UESTC 电子科大专题训练 数论 G的主要内容,如果未能解决你的问题,请参考以下文章

UESTC 电子科大专题训练 数论 L

UESTC 电子科大专题训练 DP-N

UESTC 电子科大专题训练 数据结构 N

UESTC 电子科大专题训练 数据结构 J

UESTC 电子科大专题训练 数据结构 A

UESTC 电子科大专题训练 数据结构 L