• 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
    ",(ans+mod)%mod);
        }
        return 0;
    }
  • 相关阅读:
    同一页面的不同Iframe获取数据
    同一页面的两个Iframe获取数据
    关于从SVN检出项目后,项目名称还是之前修改之前或者项目名称不对问题
    <fieldset>标签
    利用js动态创建<style>
    找换硬币问题 与 0-1背包问题区别
    某种 找换硬币问题的贪心算法的正确性证明
    部分背包问题的贪心算法正确性证明
    从 活动选择问题 看动态规划和贪心算法的区别与联系
    求解两个字符串的最长公共子序列
  • 原文地址:https://www.cnblogs.com/AKCqhzdy/p/9649218.html
Copyright © 2020-2023  润新知