zoukankan      html  css  js  c++  java
  • 【2016常州一中夏令营Day3】

    小 W 摆石子
    【问题描述】
    小 W 得到了一堆石子,要放在 N 条水平线与 M 条竖直线构成的网格的交点上。因为小 M 最喜欢矩形了,小 W 希望知道用 K 个石子最多能找到多少四边平行于坐标轴的长方形,它的四个角上都恰好放着一枚石子。
    【输入格式】
    第一行三个整数 N,M,K。
    【输出格式】
    一个非负整数,即最多的满足条件的长方形数量。
    【输入输出样例】

    rectangle.in
    3 3 8
    rectangle.out
    5

    rectangle.in
    7 14 86
    rectangle.out
    1398

    【数据规模】
    对于 50%的数据:N<=30
    对于 100%的数据:N<=30000,保证任意两点不重合,K<=N*M

     

    题解

    暴力枚举即可

    #include<iostream>
    #include<cstdlib>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    long long n,m,k,sum,ans;
    long long C(long long x){return x*(x-1)>>1;}
    long long maxx(long long a,long long b){return a>b?a:b;}
    long long work(long long x,long long y)
    {
        long long i,tans;
        tans=0;
        for(i=1;i<=y;i++)
            if(k/i+(bool)(k%i)<=x)
                tans=maxx(tans,C(k/i)*C(i)+C(k%i)*(k/i));    
            
        return tans;
    }
    
    int main()
    {
        int i,j;
        freopen("rectangle.in","r",stdin);
        freopen("rectangle.out","w",stdout);
        scanf("%d%d%d",&n,&m,&k);
        ans=maxx(work(n,m),work(m,n));
        printf("%lld",ans);
        return 0;
    }

    小 M 玩数列
    【问题描述】
    众所周知,小 M 的数学超级超级好,于是给小 W 出了一道题:
    给小 W 两个数 X,Y,其中 X ≤ Y≤ 2^31−1。
    小 W 任务就是求出 Fibonacci 数列第 X~Y 项的和除以 10000 的余数。
    然而小 W 是数学战五渣,于是只能把这个任务交给机智的你啦。
    【输入格式】
    第一行一个整数 T,表示数据组数。
    接下来 T 行,每行两个数 X,Y,意义如题所述。
    【输出格式】
    T 行,每行是一个询问的答案。
    【输入输出样例】

    fibonacci.in
    2
    1 5

    fibonacci.out
    127 255

    fibonacci.in
    1
    12

    fibonacci.out
    5976
    【数据规模】
    对于 80%的数据:T=1,Y<=10^6
    对于 100%的数据:T<=1000,Y<=2^31-1

     

    题解

    s[i]=s[i-1]+f[i]=s[i-1]+f[i-1]+f[i-2]

    矩乘优化即可

    $$
left[
egin{array}{c}
s[i]\
f[i]\
f[i-1]
end{array}

ight]
$$=
$$
left[
egin{array}{ccc}
1&1&1\
0&1&1\
0&1&0
end{array}

ight]^{i-2}
$$*
$$
left[
egin{array}{c}
s[2]\
f[2]\
f[1]
end{array}

ight]
$$

    #include<iostream>
    #include<cstdlib>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #define mod 10000
    using namespace std;
    struct hh
    {
        int a[5][5],n,m;
    };
    hh a,b,c;
    
    int t,l,r,suma,sumb,ans;
    int f[50005];
    
    hh mul(hh,hh);
    hh ff(hh,int);
    int main()
    {
        int i,j;
        freopen("fibonacci.in","r",stdin);
        freopen("fibonacci.out","w",stdout);
        scanf("%d",&t);
        a.m=a.n=b.n=3;
        b.m=1;
        for(j=1;j<=3;j++) a.a[1][j]=1;
        a.a[2][2]=a.a[2][3]=1;
        a.a[3][2]=1;
        b.a[1][1]=2;
        b.a[2][1]=b.a[3][1]=1;
        while(t--)
        {
            scanf("%d%d",&l,&r);
            if(l<=3) suma=l-1;
            else{c=mul(ff(a,l-3),b);suma=c.a[1][1];}
            if(r<=2) sumb=r;
            else{c=mul(ff(a,r-2),b);sumb=c.a[1][1];}
            ans=(sumb-suma+mod)%mod;
            printf("%d
    ",ans);
        }
        fclose(stdin);
        fclose(stdout);
        return 0;
    }
    
    hh mul(hh a,hh b)
    {
        int i,j,k;
        hh c;
        c.n=a.n;
        c.m=b.m;
        memset(c.a,0,sizeof(c.a));
        for(i=1;i<=c.n;i++)
          for(j=1;j<=c.m;j++)
            for(k=1;k<=c.n;k++)
             c.a[i][j]=(c.a[i][j]+a.a[i][k]*b.a[k][j])%mod;
        return c;
    }
    
    hh ff(hh a,int k)
    {
        int i,j;
        hh c;
        c.m=a.m;
        c.n=a.n;
        for(i=1;i<=min(c.n,c.m);i++) c.a[i][i]=1;
        for(i=1;i<=c.n;i++)
          for(j=1;j<=c.m;j++)
             if(i!=j) c.a[i][j]=0;
        while(k)
        {
            if(k&1) c=mul(a,c);
            a=mul(a,a);
            k>>=1;
        }
        return c;
    }

    小 W 计树
    【问题描述】
    小 W 千辛万苦做出了数列题,突然发现小 M 被困进了迷宫里。迷宫是一个有 N(2≤N≤1000)个顶点 M(N−1≤M≤N∗(N − 1)/2 ) 条边的无向连通图。设 dist1[i]表示在这个无向连通图中, 顶点 i 到顶点 1 的最短距离。为了解开迷宫,现在要求小 W 在这个图中删除 M − (N − 1)条边,使得这个迷宫变成一棵树。设 dist2[i]表示在这棵树中,顶点 i 到顶点 1 的距离。小 W 的任务是求出有多少种删除方案,使得对于任意的 i,满足 dist1[i]=dist2[i]。
    快点帮助小 W 救出小 M 吧!
    【输入格式】
    第一行,两个整数, N, M,表示有 N 个顶点和 M 条边。
    接下来有 M 行,每行有 3 个整数 x, y, len(1 ≤ x, y ≤ n, 1 ≤ len ≤ 100),表示顶点 x 和顶点 y 有一条长度为 len 的边。
    数据保证不出现自环、重边。
    【输出格式】
    一行两个整数,表示满足条件的方案数 mod 2147483647 的答案。
    【输入输出样例】
    treecount.in
    3 3
    1 2 2
    1 3 1
    2 3 1

    treecount.in
    2
    【样例解释】
    删除第一条边或第三条边都能满足条件,所以方案数是 2。

    【数据规模】
    对于 30%的数据:2≤N≤5,M≤10
    对于 50%的数据:满足条件的方案数不超过 10000
    对于 100%的数据:2≤N≤1000

     

    题解

    首先考虑离 1 点最近的那个点,一定和 1 点只连着一条边,则这条边是必选的;然后考察第二近的点,一种可能是和 1 点直接连的边比较近,一种可能是经过刚才最近的那个点再到 1 点的路比较近,不管是哪一种,选择都是唯一的,而剩下第三种可能是两者距离相同,这样的话两者选且只能选一个。以此类推,假设现在已经构造好了前 k 个点的一棵子树,看剩余点中到 1 点最近的点,这个点到 1 点有 k 种方法(分别是和那 k 个点连边), 其中有 m 个是可以保持最短距离的,则这一步可选的边数就是 m。一直构造,把方法数累乘,就能得到最后的结果。整个过程可以很好的符合 dijkstra 的过程,而生成树的步骤和 prim 如出一辙。

    #include<iostream>
    #include<cstdlib>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #define mod 2147483647
    using namespace std;
     
    int n,m;
    bool v[1005];
    int we[1010][1010], dis[1010];
    int last[1010];
    int tot=0;
    struct hh
    {
        int next,to,w;
    }e[2000005];
    
    long long ans=1;
    struct node 
    {
        int id,d;
    };
    node a[1005];
    queue<int> q;
     
    bool cmp(node a, node b) 
    {
        return a.d < b.d;
    }
     
    void add(int a,int b,int c) 
    {
        tot++;
        e[tot].to=b;
        e[tot].w=c;
        we[a][b]=c;
        e[tot].next=last[a];
        last[a]=tot;
    }
    
    void spfa()
    {
        int i,now;
        for(i=2;i<=n;i++) dis[i]=9999999;
        q.push(1); 
        dis[1]=0;
        while(!q.empty()) 
        {
            now=q.front(); 
            q.pop(); 
            v[now]=false;
            for(i=last[now];i;i=e[i].next) 
                if(dis[e[i].to]>dis[now]+e[i].w) 
                {
                    dis[e[i].to]=dis[now]+e[i].w;
                    if(!v[e[i].to]) 
                    {
                        v[e[i].to]=true;
                        q.push(e[i].to);
                    }
                }
        }
    }
    
    int main() 
    {
        int i,j,x,y,z,now;
        freopen("treecount.in","r",stdin);
        freopen("treecount.out","w",stdout);
        scanf("%d%d",&n,&m);
        for(i=1;i<=n;i++) 
         for(j=1;j<=n;j++) 
          we[i][j]=9999999;
        for(i=1;i<=m;i++) 
        {
            scanf("%d%d%d",&x,&y,&z);
            add(x,y,z);
            add(y,x,z);
        }
        spfa();
        for (i=1;i<=n;i++)
        {
            a[i].id=i;
            a[i].d=dis[i];
         } 
        sort(a+1,a+n+1,cmp);
        for(i=2;i<=n;i++) 
        {
            now=0;
            for(j=1;j<=i-1;j++) 
                if(a[i].d==a[j].d+we[a[i].id][a[j].id]) now++;
            ans=ans*(long long)now%mod;
        }
        printf("%lld",ans);
        fclose(stdin);
        fclose(stdout);
        return 0;
    }
  • 相关阅读:
    Hadoop 学习笔记 (十) hadoop2.2.0 生产环境部署 HDFS HA Federation 含Yarn部署
    hadoop 2.x 安装包目录结构分析
    词聚类
    Hadoop 学习笔记 (十一) MapReduce 求平均成绩
    Hadoop 学习笔记 (十) MapReduce实现排序 全局变量
    Hadoop 学习笔记 (九) hadoop2.2.0 生产环境部署 HDFS HA部署方法
    Visual Studio Code 快捷键大全(Windows)
    Eclipse安装教程 ——史上最详细安装Java &Python教程说明
    jquery操作select(取值,设置选中)
    $.ajax 中的contentType
  • 原文地址:https://www.cnblogs.com/yljiang/p/5796904.html
Copyright © 2011-2022 走看看