11.13的一套题

题目名称 笔记 括号 城堡

可执行文件名 note brackets castle

输入文件名 note.in brackets.in castle.in

输出文件名 note.in brackets.out castle.in

每个测试点时限 1 秒 1 秒 1 秒

内存限制 512MB 512MB 512MB

测试点数目 20 20 10

每个测试点分值 5 5 10

是否有部分分 否 否 否

题目类型 传统型 传统型 传统型

 


笔记
【问题描述】

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

              

 

 你现在可以选择两个数x和y,并将序列a中所有的x改成y。 x可以与y相等。 请求出序列最小可能的代价。
【输入格式】

输入第一行包含两个整数n和m。

第二行包含m个空格分隔的整数,代表序 列a。

【输出格式】

输出一行,包含一个整数,代表序列最小的代价。
【样例输入 1】
4 6
1 2 3 4 3 2
【样例输出 1】
3
【样例输入 2】
10 5
9 4 3 8 8
【样例输出 1】
6
【样例解释】

样例 1 中,最优策略为将 4 改成 3。样例 2 中,最优策略为将 9 改成 4。
【数据规模和约定】

对于30%的数据, n, m ≤ 100。

对于60%的数据, n, m ≤ 2000。

对于100%的数据, 1 ≤ n, m ≤ 100,000。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
#define LL long long
#define maxn 100010
using namespace std;
LL n,m,ans,mx;
LL a[maxn];
vector<LL>f[maxn];
LL init()
{
    LL 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;
}
LL Abs(LL x)
{
    return x>=0 ? x: -x;
}
LL Max(LL x,LL y)
{
    return x>=y ? x: y;
}
int main()
{
    freopen("note.in","r",stdin);
    freopen("note.out","w",stdout);
    n=init();m=init();
    for(LL i=1;i<=m;i++)a[i]=init();
    for(LL i=1;i<m;i++)ans+=Abs(a[i+1]-a[i]);
    for(LL i=1;i<=m;i++)
    {
        if(i>1&&a[i-1]!=a[i])f[a[i]].push_back(a[i-1]);
        if(i<m&&a[i+1]!=a[i])f[a[i]].push_back(a[i+1]);
    }
    for(LL i=1;i<=n;i++)
    {
        if(f[i].size()==0)continue;
        sort(f[i].begin(),f[i].end());
        LL sum=0,tot=0,mid=f[i].size()/2;
        for(LL j=0;j<f[i].size();j++)
        {
            sum+=Abs(f[i][j]-i);
            tot+=Abs(f[i][j]-f[i][mid]);
        }
        mx=Max(mx,sum-tot);
    }
    cout<<ans-mx<<endl;
    return 0;
}

括号
【问题描述】

有一个长度为n的括号序列,以及k种不同的括号。序列的每个位置上是哪 种括号是随机的,并且已知每个位置上出现每种左右括号的概率。求整个序列是 一个合法的括号序列的概率。 我们如下定义合法括号序列:

* 空序列是合法括号序列;
* 如果A是合法括号序列,那么lAr是合法括号序列,当且仅当l和r是同种 的左右括号;

* 如果A和B是合法括号序列,那么AB是合法括号序列。
【输入格式】

输入第一行包含两个整数n和k。

接下来的输入分为n组,每组k行。

第i组第j行包含两个实数l[i, j]和r[i, j],分别代表第i个位置上是第j类的左括号和右括号 的概率。

【输出格式】

输出一行,包含一个实数,代表序列是合法括号序列的概率。

建议保留至少 5 位小数输出。只有当你的输出与标准答案之间的绝对误差不超过10−5时,才会 被判为正确。
【样例输入 1】
2 1
1.00000 0.00000
0.00000 1.00000
【样例输出 1】
1.00000
【样例输入 2】
4 1
0.50000 0.50000
1.00000 0.00000
0.00000 1.00000
0.50000 0.50000
【样例输出 2】
0.25000
【数据规模和约定】

对于20%的数据, n ≤ 50, k = 1,所有位置的概率非 0 即 1。

另外有 30%的数据, n ≤ 34, k = 1, 前 10 个和后 10 个位置的所有概率都 是 0.5,中间剩余位置的概率非 0 即 1。

对于80%的数据, n, k ≤ 50。

对于100%的数据, 1 ≤ n ≤ 200, 1 ≤ k ≤ 50。

#include<iostream>
#include<cstdio>
#include<cstring>
#define maxn 210
using namespace std;
int n,w;
double l[maxn][maxn],r[maxn][maxn];
double dp[maxn][maxn],f[maxn][maxn],Dp[maxn][maxn];
int main()
{
    freopen("brackets.in","r",stdin);
    freopen("brackets.out","w",stdout);
    scanf("%d%d",&n,&w);
    for(int i=1;i<=n;i++)
      for(int j=1;j<=w;j++)
        scanf("%lf%lf",&l[i][j],&r[i][j]);
    for(int i=1;i<=n;i++)
      for(int j=i+1;j<=n;j++)
        for(int k=1;k<=w;k++)
          f[i][j]+=l[i][k]*r[j][k];
    for(int i=n;i>=1;i--)
    {
        for(int j=i+1;j<=n;j++)
        {
            if(i+1>j-1) Dp[i][j]=f[i][j],dp[i][j]+=f[i][j];
            else Dp[i][j]=dp[i+1][j-1]*f[i][j],dp[i][j]+=Dp[i][j];
            for(int k=i+1;k<j;k++)dp[i][j]+=Dp[i][k]*dp[k+1][j];
        }
    }
    printf("%f",dp[1][n]);
    return 0;
}

城堡
【问题描述】

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

【输入格式】

输入的第一行包含两个整数N和M。

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

【输出格式】

输出一行,包含一个整数,代表方案数对231 − 1取模得到的结果。
【样例输入】
3 3
1 2 2
1 3 1
2 3 1
【样例输出】
2
【数据规模和约定】

对于30%的数据, 2 ≤ N≤ 5, M ≤ 10。

对于50%的数据, 满足条件的方案数不超过 10000。

对于100%的数据, 2≤ N ≤ 1000, N − 1 ≤ M ≤ N(N-1)/2 , 1 ≤ w ≤ 100。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#define LL long long
#define inf 100000000
#define mod 2147483647
#define maxx 1010
#define maxn 2000010
using namespace std;
LL n,m,topt,ans=1;
LL first[maxx],f[maxx],dis[maxx],c[maxx];
struct edge
{
    LL from,to,val,next;
}e[maxn*2];
queue<LL>q;
LL init()
{
    LL 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;
}
void add(LL x,LL y,LL z)
{
    topt++;
    e[topt].from=x;
    e[topt].to=y;
    e[topt].val=z;
    e[topt].next=first[x];
    first[x]=topt;
}
void spfa()
{
    for(LL i=1;i<=n;i++)dis[i]=inf,f[i]=0;
    dis[1]=0;f[1]=1;q.push(1);
    while(!q.empty())
    {
        LL now=q.front();q.pop();f[now]=0;
        for(LL i=first[now];i;i=e[i].next)
        {
            LL to=e[i].to;
            if(dis[to]>dis[now]+e[i].val)
            {
                dis[to]=dis[now]+e[i].val;
                if(!f[to])f[to]=1,q.push(to);
            }
        }
    }
}
int main()
{
    freopen("castle.in","r",stdin);
    freopen("castle.out","w",stdout);
    n=init();m=init();
    for(LL i=1;i<=m;i++)
    {
        LL x,y,z;
        x=init();y=init();z=init();
        add(x,y,z);add(y,x,z);
    }
    spfa();
    for(LL i=1;i<=topt;i++)
    {
        LL x=e[i].from;LL y=e[i].to;
        if(dis[x]+e[i].val==dis[y])c[y]++;
    }
    for(LL i=2;i<=n;i++)
      ans=ans*c[i],ans%=mod;
    printf("%lld\n",ans);
    return 0;
}
posted @ 2016-11-14 19:57  岂是蓬蒿人  阅读(239)  评论(0编辑  收藏  举报