日常补

来源:互联网 发布:360卫士mac官方下载 编辑:程序博客网 时间:2024/05/02 00:57

D 维空间里有一个关于点的集合 S,集合中的点的第 i 维坐标 ai 满足 1≤ai≤di ,其中 di 是给定的正整数 ,所以 S 中总共有 ∏di 个点。

定义一次空间旅行是指,从 (1,1,⋯,1) 开始进行移动,每次移动只能将某一维坐标加 1 、其他维坐标不变,从而走到下一个点,然后继续进行移动,每次移动前也可以选择结束此次旅行。

问至少进行多少次空间旅行,才能将 S 中所有的点都访问至少一次。

/*https://biancheng.love/contest-ng/index.html#/123*/#include <cstdio>#include <cstring>#include <cmath>#include <queue>#include <cstring>#include <vector>#include <string>#include <stack>#include <set>#include <map>#include <iostream>#include <algorithm>using namespace std;#define MP make_pair#define PB push_backtypedef long long LL;typedef pair<int, int> Pii;const int inf = 0x3f3f3f3f;const LL INF = (1uLL << 63) - 1;const LL mod = 1000000007;const int N = 1e5 + 5;const double Pi = acos(-1.0);const int maxn = 2e6 + 5;int dp[25][maxn];int sum[25][maxn];int d[25];int n , m;int gao() {    dp[0][0] = 1;    /**        dp[i][j]表示在前i维内添加j所具有的状态数        dp[i][j] = sum(dp[i-1][k]) --------- 0 <= k <= j && j - k < di,di表示第i维的大小        dp[i-1][j]表示给第i维加上0,dp[i-1][j-1]表示给第i维加上1~~~~类推得dp[i-1][0]是给第i维的数字加上k        但是复杂度过高,用sum处理前缀和优化复杂度        所以        sum[i][j] = sum[i][j-1]+dp[i][j];        dp[i][j] = dp[i-1][j]+dp[i-1][j-1]+...+dp[i-1][j - di + 1] = sum[i-1][j] - sum[i-1][j - di];    **/    for(int i = 0; i <= m; i++)sum[0][i] = 1;    for(int i = 1; i <= n; i++) {        for(int j = 0; j <= m; j++) {            if(j < d[i]) {                dp[i][j] = sum[i - 1][j];            }            else dp[i][j] = sum[i - 1][j] - sum[i - 1][j - d[i]];            sum[i][j] = (j ? sum[i][j - 1] : 0) + dp[i][j];        }    }    int res = 0;    for(int i = 0; i <= m; i++) {        res = max(dp[n][i], res);    }    return res;}int main() {#ifdef LOCAL    freopen("in.txt", "r", stdin);#endif    int cas;    cin >> cas;    while(cas--) {        /**            画一下从(1,1,1)作为根往下拓展的图可知            (d1,d2,...dn)的答案应该是这个图中某一层的结点个数最多的个数            !!! 可以把这个问题转化成            (1,1,1,1....),分配x个1到这上面,具有的状态最多            然后就是dp了。。              ---------thx zk && from zk        **/        cin >> n;        m = - n;        for(int i = 1 ; i <= n ; i++) {            scanf("%d", &d[i]);            m += d[i];        }        cout << gao() << endl;    }}

constroy 喜欢玩多米诺骨牌,他把若干块骨牌排列成一个 n 行 m 列的矩阵准备进行游戏。

但是 constroy 太笨了,他无法用一次触碰使所有的骨牌全部倒下。于是,他从第一行第一列的骨牌开始检查,依次检查第一行第二列,第一行第三列,……,第二行第一列,第二行第二列,……,第 n 行第 m 列的骨牌。如果他检查到一块骨牌没有倒下,那么他就会触碰它。而第 i 行第 j 列立着的骨牌被触碰时,有 pi,j 的概率向下一行倒,有 qi,j 的概率向下一列倒,并触碰该方向上与其相邻的骨牌(如果存在)。

请你估计一下笨拙的 constroy 总共触碰骨牌次数的期望值是多少吧。

提示:期望值是试验中每次可能结果的概率乘以其结果的总和。

这题。。。
注意是从左到右触碰骨牌还有骨牌只往下和往右倒。。。没注意这个样例都不会推。。。

本想求出触碰次数的概率。。然后再求期望。。但是这样太难。。
然后被教了一发,先考虑
每个骨牌要被触碰的概率,因为每个骨牌最多被触碰一次,所以他们的和也就是答案要求的期望

就是从整体拆成了每个点的样子=_=不知道怎么表述
但是好像博客里的邮票那题也是这样做的。。。我还是忘了啊啊啊

然后考虑每个点如果会被触碰,那么就是上方的点不往下倒&&左边的点也不往右倒,所以p = 1 - (pa + pb - pa*pb);
这是个概率公式= =实在不行画个两个相交的圆求(1 - 并集)也可以理解= =

/*https://biancheng.love/contest-ng/index.html#/123*/#include <set>#include <cstring>#include <algorithm>#include <iostream>#include <cstdio>#include <cmath>#include <vector>#define  mp make_pair#define pb push_back#define  X first#define  Y secondusing namespace std;typedef long long LL;const int maxn = 505;int n, m;double righ[maxn][maxn],down[maxn][maxn];void init() {    int T;    scanf("%d", &T);    while(T--) {        scanf("%d%d", &n,&m);        double ans = 0;        for(int i=1;i<=n;i++)        for(int j=1;j<=m;j++)            scanf("%lf",&down[i][j]);        for(int i=1;i<=n;i++)        for(int j=1;j<=m;j++)            scanf("%lf",&righ[i][j]);        for(int i=1;i<=n;i++)        for(int j=1;j<=m;j++){            double t =1 - (down[i-1][j] + righ[i][j-1] - down[i-1][j]*righ[i][j-1]);            ans+=t;        }        printf("%.4lf\n",ans);    }}int main() {#ifdef LOCAL    freopen("in.txt", "r", stdin);#endif // LOCAL    init();    return 0;}

Tangjz 在二维平面上发现了 n 个互异的整点。

他很好奇,能否从中选出 m 个点恰好构成正多边形 (m≥3)(m≥3) 呢?

如果可以,请输出最大的 m ;如果不可以,请输出 -1 。

这题。。。因为点都是整点所以一定是正方形。。。想不到啊啊啊啊
所以就是判断m个点是否有正方形存在,剩下的就是枚举两点,再二分

0 0
原创粉丝点击