zoukankan      html  css  js  c++  java
  • [HAOI2010]计数(组合数学)(数位DP)

    原题题意也就是给的数的全排列小于原数的个数。

    我们可以很容易的想到重复元素的排列个数的公式。

    但是我们发现阶乘的话很快就会爆long long啊(如果您想写高精请便)

    之后我就尝试质因数分解。。。。但是遗憾的是太蒻了,没有成功,还是爆了。20分惨惨。最后也没有找出来哪里错了。

    最后蒟蒻只好参考题解了。。。。。

    之后我们再一考虑,会发现其实我们不需要重复元素排列个数的公式,我们只需要按照组合数的思想做即可。

    假设我们现在有m个位置可以摆放,我们先放0,个数就是(C_m^{cnt[0]}),之后就只剩(m-cnt[0])个位置了,那么(ans+=C_{m-cnt[0]}^{cnt[1]})。。以此类推。。。

    #include<iostream>
    #include<cstdlib>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    long long CC[1001][1001];
    long long C(long long n,long long m){
        if(CC[n][m]) return CC[n][m];
        if(m==1) return n;
        if(m==0||m==n) return 1;
        if(m>n) return 0;
        CC[n][m]=C(n-1,m)+C(n-1,m-1);
        return CC[n][m];
    }
    int a[10],v[100];
    long long ans;
    int n;
    string c;
    long long solve(){
        long long ans=1;
        int m=n;
        for(int i=0;i<=9;i++)
    		if(a[i])
    			ans*=C(m,a[i]),m-=a[i];
        return ans;
    }
    int main()
    {
        cin>>c;
    	for(int i=0;i<c.length();i++)
    			v[++n]=c[i]-'0',a[v[n]]++;
        int nn=n;
        for(int i=1;i<=nn;i++)
    	{
            n--;
            for(int j=0;j<v[i];j++)
            	if(a[j]) 
    				a[j]--,ans+=solve(),a[j]++;
            a[v[i]]--;
        }
        printf("%lld",ans);
    }
    

    最后蒟蒻在这里贴上自己的20分代码。。求dalao找错。。。。

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    #include<vector>
    using namespace std;
    long long ans;
    vector<int>v;
    string n;
    int dig[60],sum[10];
    
    inline long long solve(int cnt)
    {
        long long cur_ans=1;
        int a[60];
        memset(a,0,sizeof(a));
        for(int i=1;i<=cnt;i++)
        {
            int now=i;
            for(int j=2;j<=now;j++)
                while(now%j==0)
                    now/=j,a[j]++;//printf("a[%d]=%d
    ",j,a[j]);
        }
        for(int i=0;i<=9;i++)
        {
            if(sum[i]==0) continue;
            int now=sum[i];
            for(int j=2;j<=now;j++)
                while(now%j==0)
                    now/=j,a[j]--;//printf("a[%d]=%d
    ",j,a[j]);
        }
        for(int i=1;i<=50;i++)
            if(a[i]!=0)
                cur_ans*=(long long)pow(i,a[i]);
        return cur_ans;
    }
    
    int main()
    {
        cin>>n;
        for(int i=0;i<n.length();i++)
            v.push_back(n[i]-'0');
        int cnt=v.size();
        for(int i=0;i<v.size();i++)dig[i+1]=v[i];
        //for(int i=1;i<=cnt;i++) cout<<dig[i];
        //cout<<endl;
        for(int i=1;i<=cnt;i++)
        {
            int done[10];
            memset(done,0,sizeof(done));
            for(int j=i+1;j<=cnt;j++)
            {
                memset(sum,0,sizeof(sum));
                if(done[dig[j]]==0&&dig[j]<dig[i])
                {
                    done[dig[j]]=1;
                    for(int k=i+1;k<=cnt;k++)
                        sum[dig[k]]++;
                    sum[dig[i]]++;
                    sum[dig[j]]--;
                    ans+=(long long)solve(cnt-i);
                    //printf("dig[%d]=%d dig[%d]=%d ans=%lld
    ",i,dig[i],j,dig[j],ans);
                }
            }
        }
        printf("%lld
    ",ans);
        return 0;
    }
    
  • 相关阅读:
    Warning:The /usr/local/mysql/data directory is not owned by the 'mysql' or '_mysql'
    在终端中文本编辑器中显示行数:
    java环境配置:
    TypeError: 'MongoClient' object is not callable
    MongoDB安装
    多线程 -- 实现秒抓
    自动化测试淘宝美食
    自动化淘宝美食(在后台执行,不打开浏览器)
    新浪 抓取详情页
    WINDOWS 2003系统时间24小时制与12小时显示格式不一致问题与解决
  • 原文地址:https://www.cnblogs.com/fengxunling/p/9794781.html
Copyright © 2011-2022 走看看