• SRM 599 DIV 2


    rating又掉了。。。变灰色了%>_<%。250pt很简单,一眼看上去是个背包,没有多想立马写了个01背包,后面发现其实就是个简单的排序。。。因为只是需要求数量而已。500pt被我写残了,fst了,有一组极限数据超时了,我脑残的用了O(n)时间复杂度的质因数分解 10^9必定超时啊。。。。还是没想清楚就写了,真的得记住:想得多写得少,并且正确率也会提高很多。950pt思路是有了,没有时间写了,当时想用Trie统计下每个单词路径上经过了有多少个单词,然后再进行相应的计算,其实没必要用Trie,因为数据规模很小(n<=50),直接暴力搞一下就好了。

    1. 250pt MiniatureDachshund

    题意

    有一些香肠,每个香肠都有一个重量,Lun的小狗很喜欢吃香肠,如果狗狗吃了某个香肠,那么它的体重的增加量等于香肠的重量,狗狗希望吃到尽量多得香肠,但体重又不超过5000克(会给出小狗的体重),问狗狗最多能吃到多少根香肠?

    题解

    把香肠重量从小到大排下序,然后依次累加直到超过5000,也可以用背包,就是用5000减去小狗的体重作为容量,然后就是在背包中放入尽量多的香肠

    代码:

    背包搞的。。。

    class MiniatureDachshund
    {
    public:
        int maxMikan(vector <int> mikan, int weight)
        {
            int dp[5005];
            memset(dp,0,sizeof(dp));
            int v=5000-weight;
            for(size_t i=0; i<mikan.size(); i++)
                for(int j=v; j>=mikan[i]; j--)
                    dp[j]=max(dp[j],dp[j-mikan[i]]+1);
            return dp[v];
        }
    };

    2. 500pt BigFatInteger2

    题意

    给定四个整数A,B,C,D(1<=A,B,C,D<=10^9),判断AB%CD=0

    题解

    得把A和C进行质因数分解,分解成这样的形式 :p1a1*p2a2*p3a3…pnan ,对于每一个p,假设A和C指数分别为b,d,那么如果出现b*B<d*D那么AB%CD!=0,否则就是可以整除

    代码:很挫…

    map<int,int>a,b;
    int prime[MAXN],cnt=0;
    bool check[MAXN];
    void go(int x)
    {
        if(x==1)
        {
            a[1]++;
            return;
        }
        for(int i=0; i<cnt&&x>1; i++)
            if(x%prime[i]==0)
            {
                while(x%prime[i]==0)
                {
                    a[prime[i]]++;
                    x/=prime[i];
                }
            }
        if(x>1) a[x]++;
    }
    bool checks(int B,int x,int D)
    {
        if(x==1) return true;
        for(int i=0; i<cnt&&x>1; i++)
            if(x%prime[i]==0)
            {
                while(x%prime[i]==0)
                {
                    b[prime[i]]++;
                    if((LL)b[prime[i]]*(LL)D>(LL)a[prime[i]]*(LL)B) return false;
                    x/=prime[i];
                }
            }
        if(x>1) b[x]++;
        if((LL)b[x]*(LL)D>(LL)a[x]*(LL)B) return false;
        return true;
    }
    void get_prime()
    {
        int high=MAXN;
        memset(check,false,true);
        cnt=0;
        for(int i=2; i<=high; i++)
        {
            if(!check[i])
                prime[cnt++]=i;
            for(int j=0; j<cnt&&i*prime[j]<=high; j++)
            {
                check[i*prime[j]]=true;
                if(i%prime[j]==0) break;
            }
        }
    }
    class BigFatInteger2
    {
    public:
        string isDivisible(int A, int B, int C, int D)
        {
            a.clear();
            b.clear();
            get_prime();
            go(A);
            if(!checks(B,C,D))
                return "not divisible";
            return "divisible";
        }
    };

    3. 950pt SimilarNames2

    题意

    给定n个单词和整数L,要求你对n个单词进行排列,使得每个在[0,L-2]的单词i刚好是单词i+1的前缀,问总共有多少种排列方法?

    题解

    先对单词进行排序,然后暴力求出每个单词中的前缀恰好也是单词的前缀数量cnt,那么答案就是ans=sigma(C(cnt[i]-1,L-1)*(n-L)!)(0<=i<=n)(C(n,m)表示组合数)

    代码:

    #define MOD 1000000007
    typedef long long LL;
    LL dp[55][55],cnt[55];
    class SimilarNames2
    {
    public:
        bool check(string a,string b)
        {
            if(a.size()<=b.size()&&b.substr(0,a.size())==a) return true;
            return false;
        }
        void Comb()
        {
            for(int i=0; i<=50; i++)
            {
                dp[i][0]=1,dp[i][i]=1;
                for(int j=1; j<i; j++)
                    dp[i][j]=(dp[i-1][j]+dp[i-1][j-1])%MOD;
            }
        }
        int count(vector <string> names, int L)
        {
            sort(names.begin(),names.end());
            int len=names.size();
            memset(dp,0,sizeof(dp));
            for(int i=0; i<len; i++)
            {
                cnt[i]=1;
                for(int j=0; j<i; j++)
                {
                    if(check(names[j],names[i]))
                        cnt[i]=max(cnt[i],cnt[j]+1);
                }
            }
            Comb();
            LL fac=1;
            for(LL i=1; i<=len-L; i++)
                fac=(fac*i)%MOD;
            int ans=0;
            for(int i=0; i<len; i++)
                if(cnt[i]>=L)
                    ans=((LL)ans+dp[cnt[i]-1][L-1]*fac)%MOD;
            return ans;
        }
    };
  • 相关阅读:
    1023. 组个最小数
    1021. 个位数统计
    *1020. 月饼
    *1019. 数字黑洞
    1016. 部分A+B
    *1014. 福尔摩斯的约会
    *1013. 数素数
    *1012. 数字分类
    1011. A+B和C
    *1008. 数组元素循环右移问题
  • 原文地址:https://www.cnblogs.com/zjbztianya/p/3461449.html
Copyright © 2020-2023  润新知