Topcoder SRM 144 Div1 550(数学和dp问题求方案数,很有意思)

Problem Statement

 

In most states, gamblers can choose from a wide variety of different lottery games. The rules of a lottery are defined by two integers (choices and blanks) and two boolean variables (sorted and unique). choices represents the highest valid number that you may use on your lottery ticket. (All integers between 1 and choices, inclusive, are valid and can appear on your ticket.) blanks represents the number of spots on your ticket where numbers can be written.

The sorted and unique variables indicate restrictions on the tickets you can create. If sorted is set to true, then the numbers on your ticket must be written in non-descending order. If sorted is set to false, then the numbers may be written in any order. Likewise, if unique is set to true, then each number you write on your ticket must be distinct. If unique is set to false, then repeats are allowed.

Here are some example lottery tickets, where choices = 15 and blanks = 4:

  • {3, 7, 12, 14} -- this ticket is unconditionally valid.
  • {13, 4, 1, 9} -- because the numbers are not in nondescending order, this ticket is valid only if sorted = false.
  • {8, 8, 8, 15} -- because there are repeated numbers, this ticket is valid only if unique = false.
  • {11, 6, 2, 6} -- this ticket is valid only if sorted = false and unique = false.

Given a list of lotteries and their corresponding rules, return a list of lottery names sorted by how easy they are to win. The probability that you will win a lottery is equal to (1 / (number of valid lottery tickets for that game)). The easiest lottery to win should appear at the front of the list. Ties should be broken alphabetically (see example 1).

Definition

 
Class:Lottery
Method:sortByOdds
Parameters:vector <string>
Returns:vector <string>
Method signature:vector <string> sortByOdds(vector <string> rules)
(be sure your method is public)

Limits

 
Time limit (s):2.000
Memory limit (MB):64

Constraints

-rules will contain between 0 and 50 elements, inclusive.
-Each element of rules will contain between 11 and 50 characters, inclusive.
-Each element of rules will be in the format "<NAME>:_<CHOICES>_<BLANKS>_<SORTED>_<UNIQUE>" (quotes for clarity). The underscore character represents exactly one space. The string will have no leading or trailing spaces.
-<NAME> will contain between 1 and 40 characters, inclusive, and will consist of only uppercase letters ('A'-'Z') and spaces (' '), with no leading or trailing spaces.
-<CHOICES> will be an integer between 10 and 100, inclusive, with no leading zeroes.
-<BLANKS> will be an integer between 1 and 8, inclusive, with no leading zeroes.
-<SORTED> will be either 'T' (true) or 'F' (false).
-<UNIQUE> will be either 'T' (true) or 'F' (false).
-No two elements in rules will have the same name.

Examples

0) 
 
{"PICK ANY TWO: 10 2 F F"
,"PICK TWO IN ORDER: 10 2 T F"
,"PICK TWO DIFFERENT: 10 2 F T"
,"PICK TWO LIMITED: 10 2 T T"}
Returns: 
{ "PICK TWO LIMITED",
  "PICK TWO IN ORDER",
  "PICK TWO DIFFERENT",
  "PICK ANY TWO" }

The "PICK ANY TWO" game lets either blank be a number from 1 to 10. Therefore, there are 10 * 10 = 100 possible tickets, and your odds of winning are 1/100.

The "PICK TWO IN ORDER" game means that the first number cannot be greater than the second number. This eliminates 45 possible tickets, leaving us with 55 valid ones. The odds of winning are 1/55.

The "PICK TWO DIFFERENT" game only disallows tickets where the first and second numbers are the same. There are 10 such tickets, leaving the odds of winning at 1/90.

Finally, the "PICK TWO LIMITED" game disallows an additional 10 tickets from the 45 disallowed in "PICK TWO IN ORDER". The odds of winning this game are 1/45.

1) 
 
{"INDIGO: 93 8 T F",
 "ORANGE: 29 8 F T",
 "VIOLET: 76 6 F F",
 "BLUE: 100 8 T T",
 "RED: 99 8 T T",
 "GREEN: 78 6 F T",
 "YELLOW: 75 6 F F"}
Returns: { "RED",  "ORANGE",  "YELLOW",  "GREEN",  "BLUE",  "INDIGO",  "VIOLET" }

Note that INDIGO and BLUE both have the exact same odds (1/186087894300). BLUE is listed first because it comes before INDIGO alphabetically.

2) 
 
{}
Returns: { }

Empty case


题目很有意思,分4种情况,2种直接数学计算,2种dp一下就好了

很喜欢tc的这种题目

//Hello. I'm Peter.
#include<cstdio>
#include<iostream>
#include<sstream>
#include<cstring>
#include<string>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#include<functional>
#include<cctype>
#include<ctime>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
using namespace std;
typedef long long ll;
typedef long double ld;
#define peter cout<<"i am peter"<<endl
#define input freopen("data.txt","r",stdin)
#define randin srand((unsigned int)time(NULL))
#define INT (0x3f3f3f3f)*2
#define LL (0x3f3f3f3f3f3f3f3f)*2
#define gsize(a) (int)a.size()
#define len(a) (int)strlen(a)
#define slen(s) (int)s.length()
#define pb(a) push_back(a)
#define clr(a) memset(a,0,sizeof(a))
#define clr_minus1(a) memset(a,-1,sizeof(a))
#define clr_INT(a) memset(a,INT,sizeof(a))
#define clr_true(a) memset(a,true,sizeof(a))
#define clr_false(a) memset(a,false,sizeof(a))
#define clr_queue(q) while(!q.empty()) q.pop()
#define clr_stack(s) while(!s.empty()) s.pop()
#define rep(i, a, b) for (int i = a; i < b; i++)
#define dep(i, a, b) for (int i = a; i > b; i--)
#define repin(i, a, b) for (int i = a; i <= b; i++)
#define depin(i, a, b) for (int i = a; i >= b; i--)
#define pi 3.1415926535898
#define eps 1e-6
#define MOD 1000000007
#define MAXN 100100
#define N
#define M 200
struct Games
{
    string name;
    int choice;
    int blank;
    bool sort;
    bool unique;
    ll ans;
}game[M+100];
bool comp(const Games a,const Games b)
{//按ans从小到大排序,就相当于按1/ans从大到小排序,当然string name也要排字典序
    if(a.ans!=b.ans) return a.ans<b.ans;
    else return a.name<b.name;
}
void check(int sz);
int pos_colon(string s)
{//找到':'的位置,输入时候用
    int res=0;
    int len=slen(s);
    rep(i,0,len)
    {
        if(s[i]==':')
        {
            res=i;
            break;
        }
    }
    return res;
}
int idx(char c){
    return c-'0';
}
int changestringtoint(string s)
{//讲字符串数字转换成实际整数
    int len=slen(s);
    int res=0;
    int ten=1;
    depin(i,len-1,0)
    {
        res+=idx(s[i])*ten;
        ten*=10;
    }
    return res;
}
ll A(int n,int m)
{//排列问题 A(n,m)
    ll res=1,t=(ll)n;
    repin(i,1,m)
    {
        res*=t;
        t--;
    }
    return res;
}
ll powpow(int n,int m)
{//n的m次方
    ll res=1,t=(ll)n;
    repin(i,1,m)
    {
        res*=t;
    }
    return res;
}
ll dp[10][110];//dp[i][j]代表第i个位置放j这个数的时候方案数是多少
class Lottery
{
public:
    vector <string> sortByOdds(vector <string> rules)
    {
        int sz=gsize(rules);
        string s;
        rep(i,0,sz)
        {
            s=rules[i];
            int pos=pos_colon(s);
            game[i].name.clear();
            rep(j,0,pos)
            {
                game[i].name+=rules[i][j];
            }
            s.erase(0,pos+1);
            //删除后用istringstream处理,非常方便
            istringstream ss(s);
            int t=0;
            while(ss>>s)
            {
                t++;
                if(t==1) game[i].choice=changestringtoint(s);
                else if(t==2) game[i].blank=changestringtoint(s);
                else if(t==3)
                {
                    if(s[0]=='T') game[i].sort=true;
                    else game[i].sort=false;
                }
                else if(t==4)
                {
                    if(s[0]=='T') game[i].unique=true;
                    else game[i].unique=false;
                }
            }
        }
        //分4种情况计算,2种直接计算,2种dp
        int c,b;
        bool sorted,unique;
        rep(ii,0,sz)
        {
            c=game[ii].choice;
            b=game[ii].blank;
            sorted=game[ii].sort;
            unique=game[ii].unique;
            if(!sorted && !unique)
            {//可不单调可重复 直接算 pow
                game[ii].ans=powpow(c,b);
            }
            else if(!sorted && unique)
            {//可不单调不重复 A(c,b)
                game[ii].ans=A(c,b);
            }
            else if(sorted && !unique)
            {//单调可重复 dp 来做
                clr(dp);
                repin(i,1,c)
                {//初始化,代表第1个位置i这个数方案数,当然是1
                    dp[1][i]=1;
                }
                repin(i,2,b)
                {
                    repin(j,1,c)
                    {//枚举每个位置的每个数
                        repin(k,1,j)
                        {//它的答案就是上一个位置所有<=它的数的方案数之和
                            dp[i][j]+=dp[i-1][k];
                        }
                    }
                }
                game[ii].ans=0;
                repin(i,1,c)
                {//结果就是最后一个位置所有数的方案数之和
                    game[ii].ans+=dp[b][i];
                }
            }
            else if(sorted && unique)
            {//单调不重复 也是 dp,就一个地方不一样
                clr(dp);
                repin(i,1,c)
                {//初始化,代表第1个位置i这个数方案数,当然是1
                    dp[1][i]=1;
                }
                repin(i,2,b)
                {
                    repin(j,1,c)
                    {//枚举每个位置的每个数
                        rep(k,1,j)
                        {//它的答案就是上一个位置所有<它的数的方案数之和
                            dp[i][j]+=dp[i-1][k];
                        }
                    }
                }
                game[ii].ans=0;
                repin(i,1,c)
                {//结果就是最后一个位置所有数的方案数之和
                    game[ii].ans+=dp[b][i];
                }
            }
        }
        //根据要求排个序
        sort(game,game+sz,comp);
        vector<string>res;
        rep(i,0,sz)
        {//构成vetor<string>res
            res.pb(game[i].name);
        }
        return res;
    }
};


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值