zoukankan      html  css  js  c++  java
  • 五一集训:day3A

    题目:同时抛掷n个理想的正方体骰子,有多少概率使得其中若干个骰子点数和为m?

    多组数据

    对于 50% 的数据,n2

    对于 100% 的数据,1n8,1T10000,1m50

    挺好的题,在这么多天的集训里算一道清流了

    先想暴力:枚举每个骰子的点数,最后再跑一遍dfs判断

    O(6^n*2^n)死的很惨

    优化:枚举每个骰子点数,最后用完全背包判断

    O(6^n*36n)死的还行

    再优化:由于每个骰子对背包的影响是独立的,所以可以在枚举的时候顺带维护背包

    O(6^n*6n),能过,但不是最好

    注意到优化中,每一个背包状态都只有0/1,即能否组成,而f至多50个

    所以可将f压到一个long long里,状压dp即可

    O(6^n)

    顺带,这个题数据范围很大,但是有很多重复,所以应该记录哪些n已经被询问,这样避免T

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #include<cmath> 
    #include<iostream>
    using namespace std;
    #define O(x) cout << #x << " " << x << endl;
    #define B cout << "breakpoint" << endl;
    inline int read()
    {
        int ans = 0,op = 1;
        char ch = getchar();
        while(ch < '0' || ch > '9')
        {
            if(ch == '-') op = -1;
            ch = getchar();
        }
        while(ch >= '0' && ch <= '9')
        {
            (ans *= 10) += ch - '0';
            ch  = getchar();
        }
        return ans * op;
    }
    #define clr(a) memset(a,0,sizeof(a));
    int ans[10][50];
    bool f[50];
    int a[50];
    int n,m;
    void dfs(int cur)//cur:第几个 
    {
        if(cur == n + 1)
        {
            for(int j = 1;j <= 48;j++)
                ans[n][j] += f[j];
            return;
        }
        for(int i = 1;i <= 6;i++)//cur的值是啥 
        {
            a[cur] = i;
            vector<int> tp;
            for(int j = 6 * n;j >= a[cur];j--) 
            {
                if(f[j] == 0 && f[j - a[cur]]) tp.push_back(j);
                f[j] |= f[j - a[cur]];
            }
            dfs(cur + 1);
            for(int j = 0;j < tp.size();j++) f[tp[j]] = 0;
        }
    }
    int gcd(int x,int y) { return !y ? x : gcd(y,x % y); }
    bool exist[10];
    int main()
    {
        int t = read();
        while(t--)
        {
        f[0] = 1;
        n = read(),m = read();
        if(m > 48) {printf("0/1
    "); continue; }
        if(!exist[n]) exist[n] = 1,dfs(1);
        int base = pow(6,n);
        int g = gcd(ans[n][m],base);
        printf("%d/%d
    ",ans[n][m] / g,base / g);
        }
    }
    View Code
  • 相关阅读:
    企业微信api接口调用-触发推送企业微信微信好友
    企业微信api接口调用-触发推送企业微信微信好友
    企业微信api接口调用-企业微信好友收发消息
    抖音api接口调用-同步抖音推荐的好友
    <转载>医学图像存储与传输系统(PACS)
    <转载>RESTful API 最佳实践
    <转载>DICOMweb——将DICOM影像接入互联网
    API设计规范---RESTful架构详解
    开源医学影像平台---Cornerstonejs开发指南
    开源医学影像平台---Cornerstonejs学习笔记<5>
  • 原文地址:https://www.cnblogs.com/LM-LBG/p/10845692.html
Copyright © 2011-2022 走看看