11.13 模拟题

来源:互联网 发布:太原软件 编辑:程序博客网 时间:2024/05/01 21:20

笔记

【问题描述】

给定一个长度为m的序列a,下标编号为1~m。序列的每个元素都是1~n的

整数。定义序列的代价为
这里写图片描述
你现在可以选择两个数x和y,并将序列a中所有的x改成y。x可以与y相等。
请求出序列最小可能的代价。

【输入格式】

输入第一行包含两个整数n和m。第二行包含m个空格分隔的整数,代表序列a。

【输出格式】

输出一行,包含一个整数,代表序列最小的代价。

【样例输入 1】

4 61 2 3 4 3 2

【样例输出 1】

3

【样例输入 2】

10 59 4 3 8 8

【样例输出 1】

6

【样例解释】

样例 1 中,最优策略为将 4 改成 3。样例 2 中,最优策略为将 9 改成 4。

【数据规模和约定】

这里写图片描述

代码:

/*统计出每个点 与他相邻的点sort后找中位数 中位数对ans的贡献一定是最小的 */#include<cstdio>#include<cmath>#include<iostream>#include<algorithm>#include<vector> using namespace std;int n,m,a[100001];long long ans,s;vector<int>b[100001];inline void  read(int&x) {    int f=1;x=0;char c=getchar();    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}    while(c>='0'&&c<='9') x=x*10+c-48,c=getchar();    x=x*f;}int main(){    freopen("note.in","r",stdin);    freopen("note.out","w",stdout);    read(n);read(m);    for(int i=1;i<=m;i++) read(a[i]);    for(int i=1;i<=m;i++) {        if(i>1&&a[i-1]!=a[i]) b[a[i-1]].push_back(a[i]);        if(i<m&&a[i+1]!=a[i]) b[a[i+1]].push_back(a[i]);    }    for(int i=1;i<=n;i++) {        if(!b[i].size()) continue;        sort(b[i].begin(),b[i].end());        int y=b[i][b[i].size()>>1];        long long be=0,after=0;        for(int j=0;j<b[i].size();j++) {            be+=abs(i-b[i][j]);            after+=abs(y-b[i][j]);        }        ans=max(ans,be-after);        s+=be;    }    cout<<s/2-ans;    fclose(stdin);    fclose(stdout);    return 0;}

城堡

【问题描述】

给定一张n个点m条边的无向连通图,每条边有边权。我们需要从m条边中选出n-1条,构成一棵树。记原图中从 1 号点到每个节点的最短路径长度为Di 树中从1号点到每个节点的最短路径长度为Si ,构出的树应当满足对于任意节点i,都有Di=Si 。请你求出选出n-1条边的方案数。

【输入格式】

输入的第一行包含两个整数n和m。接下来m行,每行包含三个整数u、v和w,描述一条连接节点u和v且边权为w的边。

【输出格式】

输出一行,包含一个整数,代表方案数对2^31−1取模得到的结果。

【样例输入】

3 31 2 21 3 12 3 1

【样例输出】

2

【数据规模和约定】

这里写图片描述

代码:

/*最短路计数 */#include<iostream>#include<cstdio>#include<queue>#define lon long longusing namespace std;const int maxn=10010;const long long mod=0x7fffffff;lon n,m,tot,c[maxn],head[maxn],dis[maxn];bool flag[maxn];struct node {    lon to;    lon from;    lon w;    lon next;}e[1000010];inline lon init() {    lon x=0,f=1;char c=getchar();    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}    while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}    return x*f;}inline void add_edge(lon u,lon v,lon w) {    e[++tot].to=v;    e[tot].from=u;    e[tot].w=w;    e[tot].next=head[u];    head[u]=tot;}inline void spfa() {    for(lon i=1;i<=n;i++) dis[i]=0x7fffffff;dis[1]=0;    queue<lon> q;    q.push(1);flag[1]=1;    while(!q.empty()) {        lon u=q.front();        q.pop();flag[u]=0;        for(lon i=head[u];i;i=e[i].next) {            lon v=e[i].to;            if(dis[v]>dis[u]+e[i].w) {                dis[v]=dis[u]+e[i].w;                if(!flag[v]) {                    q.push(v);                    flag[v]=1;                }            }        }    }}int main() {    freopen("castle.in","r",stdin);    freopen("castle.out","w",stdout);    lon x,y,z;    n=init();m=init();    for(lon i=1;i<=m;i++) {        x=init();y=init();z=init();        add_edge(x,y,z);        add_edge(y,x,z);    }    spfa();    lon ans=1;    for(int i=1;i<=tot;i++) {        lon u=e[i].from;        lon v=e[i].to;        if(dis[v]==dis[u]+e[i].w)        c[v]++;    }    for(int i=2;i<=n;i++)    ans=(ans*c[i])%mod;    cout<<ans;    fclose(stdin);fclose(stdout);    return 0;}

括号

【问题描述】

有一个长度为n的括号序列,以及k种不同的括号。序列的每个位置上是哪种括号是随机的,并且已知每个位置上出现每种左右括号的概率。求整个序列是一个合法的括号序列的概率。我们如下定义合法括号序列:    空序列是合法括号序列;    如果A是合法括号序列,那么lAr是合法括号序列,当且仅当l和r是同种的左右括号;    如果A和B是合法括号序列,那么AB是合法括号序列。

【输入格式】

输入第一行包含两个整数n和k。接下来的输入分为n组,每组k行。第i组第j行包含两个实数l[i,j]和r[l,r],分别代表第i个位置上是第j类的左括号和右括号的概率。

【输出格式】

输出一行,包含一个实数,代表序列是合法括号序列的概率。建议保留至少5 位小数输出。只有当你的输出与标准答案之间的绝对误差不超过10 −5 时,才会被判为正确。

【样例输入 1】

2 11.00000 0.000000.00000 1.00000

【样例输出 1】

1.00000

【样例输入 2】

4 10.50000 0.500001.00000 0.000000.00000 1.000000.50000 0.50000

【样例输出 2】

0.25000

【数据规模和约定】

这里写图片描述

代码:

//区间DP#include <cstdio>#include <cstdlib>using namespace std;const int N = 200;const int K = 50;int n, k;double l[N + 1][K + 1], r[N + 1][K + 1];double f[N + 1][N + 1], g[N + 1][N + 1];int main() {    freopen("brackets.in", "r", stdin);    freopen("brackets.out", "w", stdout);    scanf("%d%d", &n, &k);    for (int i = 1; i <= n; ++i)        for (int j = 1; j <= k; ++j)            scanf("%lf%lf", &l[i][j], &r[i][j]);    for (int i = 0; i <= n; ++i)        f[i + 1][i] = 1;    for (int len = 2; len <= n; len += 2)        for (int i = 1; i <= n - len + 1; ++i) {            for (int m = 1; m <= k; ++m)                f[i][i + len - 1] += (f[i + 1][i + len - 2] + g[i + 1][i + len - 2]) * l[i][m] * r[i + len - 1][m];            for (int mid = i + 1; mid <= i + len - 2; mid += 2)                g[i][i + len - 1] += f[i][mid] * (f[mid + 1][i + len - 1] + g[mid + 1][i + len - 1]);        }    double ans = f[1][n] + g[1][n];    printf("%.5lf\n", ans);    fclose(stdin);    fclose(stdout);    return 0;}
0 0
原创粉丝点击