bzoj4737: 组合数问题

终于过了肝了一天啊,怎么我最近都在做细节码农题啊

(这种水平NOIP凉凉??)

luacs大家都可以想到用吧,一开始我的思路是把所有在p以内的%p==0的组合数预处理出来,那C(n/p,m/p)任取,但是好像有重算

仔细思考,其实一个组合数可以拆分成很多个C(x%p,y%p) x<y就有是k的倍数,把这个东西看成p进制,得到推论C(i,j)不是p的倍数当且仅当k进制下i的每一位分别大于等于j

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long LL;
const LL mod=1e9+7;

int alen,a[110],blen,b[110];
LL S(LL x){return x%=mod,x*(x+1)/2%mod;}
LL cal(LL a,LL b)
{
    if(a<b)b=a;
    return (S(a)-S(a-b))%mod;
}
LL f[110][2][2];//第i个位,是否在n的上界边缘,是否在m的上界边缘,每一位i都大于等于j的方案数 
int main()
{
    freopen("a.in","r",stdin);
    freopen("a.out","w",stdout);
    int T,K;
    scanf("%d%d",&T,&K);
    while(T--)
    {
        LL n,m,k;
        scanf("%lld%lld",&n,&m);if(n<m)m=n;
        alen=0,k=n;while(k>0)a[++alen]=k%K,k/=K;
        blen=0,k=m;while(k>0)b[++blen]=k%K,k/=K;
        for(int i=blen+1;i<=alen;i++)b[i]=0;
                
        int len=alen;
        memset(f,0,sizeof(f));
        for(int u=0;u<=a[len];u++)
            for(int v=0;v<=b[len];v++)
            {
                if(u>=v)
                {
                    if(u==a[len]&&v==b[len])f[len][1][1]++;
                    else if(u==a[len])f[len][1][0]++;
                    else if(v==b[len])f[len][0][1]++;
                    else f[len][0][0]++;
                }
            }
        int c;
        for(int i=len-1;i>=1;i--)
        {
            c=0;
            for(int u=0;u<K;u++)
                for(int v=0;v<K;v++)
                {
                    if(u>=v)
                    {
                        if(u<a[i])
                        {
                            if(v<b[i])
                            {
                                c++;
                                f[i][0][0]=(f[i][0][0]+f[i+1][0][0]+f[i+1][0][1]+f[i+1][1][0]+f[i+1][1][1])%mod;
                            }
                            if(v==b[i])
                            {
                                f[i][0][0]=(f[i][0][0]+f[i+1][0][0]+f[i+1][1][0])%mod;
                                f[i][0][1]=(f[i][0][1]+f[i+1][0][1]+f[i+1][1][1])%mod;
                            }
                            if(v>b[i])
                            {
                                f[i][0][0]=(f[i][0][0]+f[i+1][0][0]+f[i+1][1][0])%mod;
                            }
                        }
                        if(u==a[i])
                        {
                            if(v<b[i])
                            {
                                f[i][0][0]=(f[i][0][0]+f[i+1][0][0]+f[i+1][0][1])%mod;
                                f[i][1][0]=(f[i][1][0]+f[i+1][1][0]+f[i+1][1][1])%mod;
                            }
                            if(v==b[i])
                            {
                                f[i][0][0]=(f[i][0][0]+f[i+1][0][0])%mod;
                                f[i][0][1]=(f[i][0][1]+f[i+1][0][1])%mod;
                                f[i][1][0]=(f[i][1][0]+f[i+1][1][0])%mod;
                                f[i][1][1]=(f[i][1][1]+f[i+1][1][1])%mod;
                            }
                            if(v>b[i])
                            {
                                f[i][0][0]=(f[i][0][0]+f[i+1][0][0])%mod;
                                f[i][1][0]=(f[i][1][0]+f[i+1][1][0])%mod;
                            }
                        }
                        if(u>a[i])
                        {
                            if(v<b[i])
                            {
                                f[i][0][0]=(f[i][0][0]+f[i+1][0][0]+f[i+1][0][1])%mod;
                            }
                            if(v==b[i])
                            {
                                f[i][0][0]=(f[i][0][0]+f[i+1][0][0])%mod;
                                f[i][0][1]=(f[i][0][1]+f[i+1][0][1])%mod;
                            }
                            if(v>b[i])
                            {
                                f[i][0][0]=(f[i][0][0]+f[i+1][0][0])%mod;
                            }
                        }
                    }
                }
        }
        
        LL ans=cal(n+1,m+1);
        for(int i=0;i<=1;i++) 
            for(int j=0;j<=1;j++)
                ans=(ans-f[1][i][j])%mod;
        printf("%lld\n",(ans+mod)%mod);
    }
    return 0;
}

 

posted @ 2018-09-14 22:04  AKCqhzdy  阅读(281)  评论(0编辑  收藏  举报