2018.10.16考試

2018.10.16考試總結

1 、購物

(shop.pas/c/cpp)ios

【題目描述】

小林來到商店中進行購物。 商店裏一共有 n 件物品, 第 i 件物品的價格爲 a[i]元。小林總共須要購買 m 件物品,他但願他所花費的錢最少,請你計算出最小花費。
因爲輸入的數據數量過大,咱們採用一種加密的方式進行輸入。給出兩個密鑰 x 和 y。則 a[1] = x, a[i] = (y*a[i-1] + x) % 10^9。ui

【輸入格式】

一行兩個整數 n 和 m。
第二行共兩個整數 x 和 y,表示密鑰。加密

【輸出格式】

輸出只有一個整數,表示最小花費。spa

【樣例輸入】

5 3
2 9rest

【樣例輸出】

204code

【數據規模】

對於 50%的數據,n <= 1000;
對於 100%的數據,1 <= n <= 10^7, 1 <= m <= 100, 1 <= x,y < 10^9。
對於 100%的數據,保證 m <= n。隊列

題目很好懂,暴力很好想,可是數據太大正解沒想到,正解是用堆或優先隊列維護m個最小值
人傻就要多作題ci

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#define int long long
using namespace std;
const int mod=1e9;
int n,m,x,y,ans,a[10000010];
priority_queue<int> q;
signed main()
{
    cin>>n>>m>>x>>y;
    a[1]=x;
    for(int i=2;i<=n;++i)
        a[i]=(y*a[i-1]+x)%mod;
    for(int i=1;i<=m;++i)
        q.push(a[i]);
    for(int i=m+1;i<=n;++i)
    {
        if(q.top()>a[i])
        {
            q.pop();
            q.push(a[i]);
        }
    }
    while(!q.empty())
    {
        ans+=q.top();
        q.pop();
    }
    cout<<ans<<"\n";
    return 0;
}

2 、指望

(exp.pas/c/cpp)get

【題目描述】

咱們知道,若一個隨機變量 X,在 pi 的機率下,它的值等於 xi,則它的數學指望\(E(X)=\sum_{i} p_i x_i\),且知足\(\sum_{i}p_i=1\)
如今有以下一個表達式:
0 a1 b1 a2 b2 ... an bn
其中 ai 爲一個位運算符,是「和」「或」「異或」三者中的一種,bi 是一個整數。
求這一表達式的值是一件容易的事,然而剛學完數學指望的小林在思考,若是每一對 ai bi 有 ci 的機率會消失,那麼這一表達式的結果的數學指望是多少。數學

【輸入格式】

第一行只有一個正整數 n。
第二行爲 n 個整數表示 n 個運算符 ai,0 表示 and,1 表示 or,2 表示 xor。
第三行爲 n 個非負整數 bi。
第四行爲 n 個實數 ci(不超過三位小數)。

【輸出格式】

只有一個實數,表示表達式的數學指望,保留一位小數。

【樣例輸入】

2
1 2
5 7
0.5 0.5

【樣例輸出】

3.5

【數據規模】

對於 30%的數據,1 <= n <= 10,0 <= bi <= 20;
對於 70%的數據,1 <= n <= 100,0 <= bi <= 1000;
對於 100%的數據,1 <= n <= 100000,0 <= ai <= 2,0 <= bi < 2^31。
對於 100%的數據,0 <= ci <= 0.999。

指望沒學過啊,看了看題,瞎寫寫dfs 居然能過40,數據太水了
正解確定是指望dp啊,轉移方程見代碼
40分暴力

#include<iostream>
#include<cstdio>
using namespace std;
double ans,c[110],d[110];
int n,a[110],b[110];
void dfs(int now,int z,double jl)
{
    if(now>n)
    {
        ans+=(double)(jl*z);
        return ;
    }
    if(a[now]==0)
    {
        dfs(now+1,z&b[now],jl*d[now]);
        dfs(now+1,z,jl*c[now]);
    }
    if(a[now]==1)
    {
        dfs(now+1,z|b[now],jl*d[now]);
        dfs(now+1,z,jl*c[now]);
    }
    if(a[now]==2)
    {
        dfs(now+1,z^b[now],jl*d[now]);
        dfs(now+1,z,jl*c[now]);
    }
}
int main()
{
    freopen("exp.in","r",stdin);
    freopen("exp.out","w",stdout);
    cin>>n;
    for(int i=1;i<=n;++i)
        cin>>a[i];
    for(int i=1;i<=n;++i)
        cin>>b[i];
    for(int i=1;i<=n;++i)
        cin>>c[i],d[i]=1-c[i];
    dfs(1,0,1);
    printf("%.1lf\n",ans);
    return 0;
}

正解

#include<iostream>
#include<cstdio>
const int N=100010;
double f[N][34];
int a[N],b[N];
double c[N];
int main()
{
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;++i)scanf("%d",&a[i]);
    for(int i=1;i<=n;++i) scanf("%d",&b[i]);
    for(int i=1;i<=n;++i) scanf("%lf",&c[i]);
    for(int i=1;i<=n;++i)
        for(int j=0;j<=31;++j)
        {
            if(a[i]==0)
            {
                if(b[i]&(1<<j))
                {
                    f[i][j]=(1-c[i])*f[i-1][j];
                    f[i][j]+=c[i]*f[i-1][j];
                }
                else
                {
                    f[i][j]=0;
                    f[i][j]+=c[i]*f[i-1][j];
                }
            }
            if(a[i]==1)
            {
                if(b[i]&(1<<j))
                {
                    f[i][j]=(1-c[i]);
                    f[i][j]+=c[i]*f[i-1][j];
                }
                else
                {
                    f[i][j]=(1-c[i])*f[i-1][j];
                    f[i][j]+=c[i]*(f[i-1][j]);
                }
            }
            if(a[i]==2)
            {
                if(b[i]&(1<<j))
                {
                    f[i][j]=(1-c[i])*(1-f[i-1][j]);
                    f[i][j]+=c[i]*(f[i-1][j]);
                }
                else
                {
                    f[i][j]=(1-c[i])*f[i-1][j]; 
                    f[i][j]+=c[i]*f[i-1][j];
                }
            }
        }
    double ans=0;
    for(int i=0;i<=32;++i)
        ans+=(1<<i)*f[n][i];
    printf("%.1lf",ans);
    return 0;
}

3 3 、 魔法迷宮

(maze.pas/c/cpp)

【題目描述】

在建立了魔法森林後,亮亮興致不減,因而揮動魔杖,又創造了魔法迷宮。魔法迷宮共有 n 個節點,由 n-1 條邊將它們相連,整個迷宮是連通的。邊的長度只有 A 和 B 兩種。如今有 m 只小精靈,第 i 只小精靈一開始在 ui 點,她想要到達 vi 點,每一天,它最多移動 ki 的距離,並且她不能停留在某一條邊上。你的任務是,計算出每一隻小精靈到達本身的目的地至少須要幾天。

【輸入格式】

第一行一個整數 n。
接下來 n-1 行,每行三個整數 x, y, z, 表示 x,y 之間有一條長度爲 z 的邊。
隨後一行一個整數 m,表示共有 m 只小精靈。
接下來 m 行,每行三個整數 ui, vi, ki。(保證 B≤ki≤n)

【輸出格式】

輸出共 m 行,每行一個整數表示答案。

【樣例輸入】

3
1 2 1
2 3 2
2
1 2 3
2 3 3

【樣例輸出】

1
1

【數據規模】

對於 20%的數據,n,m <= 5000;
對於 100%的數據,1 <= n,m <= 50000,1 <= A < B <= 37
鬼畜題,什麼鬼,不會,瞎寫了一下,不但寫錯了,並且freopen還不當心刪了,無輸出
正解:預處理每個點往上連續走六步會出現的各類狀況,控制常數,從而在 8 秒內出解。因爲邊權只有兩種,因此一個點往上走六步遇到的邊權只有 2^6 = 64 種狀況。

#include<cstdio>
#include<cstring>
#include<iostream>
#define E 50010
#define F 100010
using namespace std;
int n,m,head[E],to[F],next[F],value[F],cnt=0,cost=0,costa=0;
void add(int x,int y,int z)
{
    to[++cnt]=y;
    value[cnt]=z;
    next[cnt]=head[x];
    head[x]=cnt;
}
int fa[E][20],dep[E],dist[E][7],type[E],jky[E][300],dd[E],jump[E];
short czy[1<<8][300][300][2];
void dfs(int u, int f, int d)
{
    fa[u][0]=f;
    dep[u]=d;
    for(int j=head[u];j;j=next[j])
    {
        int v=to[j];
        if(v==f) continue;
        dist[v][0]=value[j];
        dfs(v,u,d+1);
    }
}
void build()
{
    for(int k=1;k<20;k++)
        for(int u=1;u<=n;u++)
        {
            fa[u][k]=fa[fa[u][k-1]][k-1];
            if(k<=5) dist[u][k]=dist[u][k-1]+dist[fa[u][k-1]][k-1];
        }
    for(int i=1;i<=n;i++)
        if(dep[i]>=6) dd[i]=dist[i][2]+dist[fa[i][2]][1];
    for(int i=1;i<=n;i++)
    {
        if(dep[i]<6) continue;
        int t=0,u=i;
        for(int j=0;j<6;j++)
        {
            if(dist[u][0]==cost) t+=1<<j;
            u=fa[u][0];
        }
        jump[i]=u;
        type[i]=t;
    }
    for(int j=0;j<(1<<6);j++)
        for(int k=cost;k<=cost*6;k++)
            for(int rest=0;rest<=k;rest++)
            {
                int path=j,step=0,re=rest;
                for(int t=1;t<=6;t++)
                {
                    int co;
                    if(path&1) co=cost;
                    else co=costa;
                    if(re<co) re=k,step++;
                    re-=co;
                    path>>=1;
                }
                czy[j][k][rest][0]=step;
                czy[j][k][rest][1]=re;
            }
    for(int i=1;i<=n;i++)
    {
        int u=i,rest=0;
        for (int j=0;j<dd[i];j++)
        {
            if(dep[u]>0&&rest>=dist[u][0])
            {
                rest-=dist[u][0];
                u=fa[u][0];
            }
            jky[i][j]=u;
            rest++;
        }
    }
}
int get(int x, int y)
{
    if(dep[x]<dep[y]) swap(x,y);
    for(int k=19;k>=0;k--)
        if(dep[fa[x][k]]>=dep[y]) x=fa[x][k];
    if(x==y) return x;
    for(int k=19;k>=0;k--)
        if(fa[x][k]!=fa[y][k]) x=fa[x][k],y=fa[y][k];
    if (x!=y) x=fa[x][0];
    return x;
}
struct hyd
{
    int step,rest;
};
inline hyd work(int u,int f,int k)
{
    int step=0,rest=0;
    if(k<=cost*6)
        while (dep[u]>dep[f])
        {
            if(dep[u]-dep[f]<6)
            {
                if(rest>=dist[u][0]) rest-=dist[u][0];
                else step++,rest=k-dist[u][0];
                u=fa[u][0];
                continue;
            }
            step+=czy[type[u]][k][rest][0];
            rest=czy[type[u]][k][rest][1];
            u=jump[u];
        }
    else
        while(dep[u]>dep[f])
        {
            if(rest==0) step++,rest=k;
            if(dep[u]-dep[f]<6)
            {
                if(rest>=dist[u][0]) rest-=dist[u][0];
                else step++,rest=k-dist[u][0];
                u=fa[u][0];
                continue;
            }
            if(rest>=dd[u])
            {
                rest-=dd[u];
                u=jump[u];
                continue;
            }
            u=jky[u][rest],rest=0;
        }
    return (hyd){step,rest};
}
int main()
{
    scanf("%d",&n);
    memset(head,0,sizeof(head));
    for(int i=1;i<n;i++)
    {
        int x,y,z;
        scanf("%d%d%d",&x,&y,&z);
        add(x,y,z);
        add(y,x,z);
        if(cost<z) cost=z;
        if(i==1) costa=z;
        else if(costa>z) costa=z;
    }
    memset(fa,0,sizeof(fa));
    memset(dep,0,sizeof(dep));
    memset(dist,0,sizeof(dist));
    dfs(1,0,0);
    build();
    scanf("%d",&m);
    for(int i=1;i<=m;i++)
    {
        int x,y,k;
        scanf("%d%d%d",&x,&y,&k);
        int f=get(x,y);
        hyd ans1=work(x,f,k),ans2=work(y,f,k);
        int ans=ans1.step+ans2.step;
        ans-=(ans1.rest+ans2.rest)/k;
        printf("%d\n",ans);
    }
    return 0;
}
相關文章
相關標籤/搜索