srm 542

资瓷点击此处阅读该文章O_o

250


Description

从矩形地图中选三个点,使得A-B,B-C,C-A的曼哈顿距离和在给定的一个范围内,求多少种选法。 X,Y3000

Solution

水题,很容易发现曼哈顿距离和是一个矩形的周长,枚举长和宽统计即可。

Code

#include <bits/stdc++.h>
using namespace std;
#define pb push_back
#define mp make_pair
#define F first
#define S second
typedef long long LL;
typedef pair<int, int> pii;
const int M = 1e9 + 7;
const int N = 5000;
struct PatrolRoute {
    int countRoutes(int X, int Y, int minT, int maxT) {
        LL ans = 0;
        for (int i = 2; i < X; ++i)
            for (int j = 2; j < Y; ++j) {
                if ((i + j) * 2 >= minT && (i + j) * 2 <= maxT) {
                    ans += 1ll * (X - i) * (Y - j) % M * (i - 1) % M * (j - 1) % M;
                }
            }
        return ans * 6 % M;
    }
};

500


Description

给出 n 个长度都为m的字符串。 n16,m50 ,任两个字符串之间的大小关系由一个随即产生的排列来决定。即,如果比较至第 i 位,则去比较pai pbi 的大小关系,从而确定字符串的大小关系。问 wordsi 排完序后是最小串的概率。

Solution

感觉这题很难QAQ,首先n=16可以想到状压Dp,但是状态很难想,看了别人的题解才会做。。
dp[i][mask] 表示当前状态是 mask ,第 i 个人是最小串的概率,mask为i的位置表示该串已被选择。在统计第 i 个串的概率时同时记录每位字母对应比该串小的和相等的状态。分别用small[j] same[j] 存二进制状态。
small[j]&mask>0 时,显然不可以转移,当 same[j]&mask=mask 时,转移没什么意义,否则 dp[i][mask]+=dp[i][same[j]&mask]

Code

//状压Dp
#include <bits/stdc++.h>
using namespace std;
#define pb push_back
#define mp make_pair
#define F first
#define S second
typedef long long LL;
typedef pair<int, int> pii;
const int N = 16;
int small[51], same[51];
vector<double> ans; 
double dp[N][1 << N];
double gao(int x, int mask, int l) {
    if (dp[x][mask] != -1.0)    return dp[x][mask];
    double &t = dp[x][mask];
    if (mask == (1 << x))   return t = 1.0;
    t = 0.0;
    int cnt = 0;
    for (int i = 0; i < l; ++i) {
        if ((small[i] & mask) > 0)  ++cnt;
        else if ((same[i] & mask) != mask)  ++cnt, t += gao(x, mask & same[i], l);
    }
    t /= cnt;
    return t;
}
struct StrangeDictionary2 {
    vector <double> getProbabilities(vector <string> words) {
        int n = words.size(), l = words[0].size();
        for (int i = 0; i < n; ++i)
            for (int j = 0; j < 1 << n; ++j)
                dp[i][j] = -1.0;
        for (int i = 0; i < n; ++i) {
            memset(small, 0, sizeof(small));
            memset(same, 0, sizeof(same));
            for (int k = 0; k < l; ++k)
                for (int j = 0; j < n; ++j) {
                    if (words[j][k] < words[i][k])  small[k] |= 1 << j;
                    else if (words[j][k] == words[i][k])    same[k] |= 1 << j;
                }
            ans.pb(gao(i, (1 << n) - 1, l));
        }
        return ans;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值