250
Description 从矩形地图中选三个点,使得A-B,B-C,C-A的曼哈顿距离和在给定的一个范围内,求多少种选法。$X,Y\le 3000$
Solution 水题,很容易发现曼哈顿距离和是一个矩形的周长,枚举长和宽统计即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 #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 += 1l l * (X - i) * (Y - j) % M * (i - 1 ) % M * (j - 1 ) % M; } } return ans * 6 % M; } };
500
Description 给出$n$个长度都为$m$的字符串。$n\le 16, m\le 50$,任两个字符串之间的大小关系由一个随即产生的排列来决定。即,如果比较至第$i$位,则去比较$pa_i$和$pb_i$的大小关系,从而确定字符串的大小关系。问$words_i$排完序后是最小串的概率。
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]$
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 #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; } };