zoukankan      html  css  js  c++  java
  • 前缀和优化例题1(【Usaco Oct08 Gold】建造栅栏(Building A Fence))

    题目如下
    问题描述

    勤奋的Farmer John想要建造一个由四面围成的栅栏来关住那些奶牛。他现在有一块长度为N(4 <= N <=100000)的长木板,他需要把这块长木板切成边长均为正整数的四块,使得他能建造一个栅栏。请问他有多少种不同的切割方式能使切割出来的木板围成一个四面的栅栏。
    注意:
    1.    四边形即可,不一定是矩形。
    2.    栅栏围成的面积必须大于0且木板必须用完
    3.    结果可以用64位整数存储, 只要大木板的切割点不同就当成是不同的方案

    输入格式

    仅一行,整数N

    输出格式

    仅一行,Farmer John能将木板分割开来并能围成四边形的方案数。

    样例输入

    6

    样例输出

    6

    提示

    样例解释:
    Farmer John有10中方法将木板分成四块:(1, 1, 1,3); (1, 1, 2, 2); (1, 1, 3, 1); (1, 2, 1, 2); (1, 2, 2, 1); (1, 3,1, 1); (2, 1, 1, 2); (2, 1, 2, 1); (2, 2, 1, 1);(3, 1, 1, 1).

    其中有四种情况是不能围成一个四边形的:(1, 1, 1, 3), (1, 1, 3, 1), (1, 3, 1, 1), (3,1, 1, 1)

     
    分析
    构成四边形的条件:
    任意一边长度 < 周长/2
    证明:设四边为a,b,c,d
    因为有a < b+c+d,所以2*a < a+b+c+d = 周长,所以a < 周长/2


    *f[i][j]:i条边,总长为j的方案数
    求=f[4][n];
    for(int i=1;i<=4;i++)
    for(int j=1;j<=n;j++)
    int k=min(j,Len);
    f[i][j]=f[i-1][j-k](1<=k<min(j,n/2))=sum[i-1][j-1]-sum[i-1][max(j-k-1,0)];
    sum[i][j]=sum[i][j-1]+f[i][j];
    }
    代码如下
    #include<stdio.h>
    #include<bits/stdc++.h>
    #define res register long long
    using namespace std;
    #pragma GCC optimize(2)
    #pragma GCC optimize(3)
    #pragma GCC optimize("Ofast")
    #pragma GCC optimize("inline")
    #pragma GCC optimize("-fgcse")
    #pragma GCC optimize("-fgcse-lm")
    #pragma GCC optimize("-fwhole-program")
    #pragma GCC optimize("-freorder-blocks")
    #pragma GCC optimize("-fschedule-insns")
    #pragma GCC optimize("inline-functions")
    #pragma GCC optimize("-ftree-tail-merge")
    long long f[5][100005];
    long long sum[5][100005];
    int n,Len;
    inline int read()  
    {
        int s=0;
        char c=getchar();
        while (c<'0' || c>'9') c=getchar();
        while (c>='0' && c<='9') s=s*10+c-'0',c=getchar();
        return s;
    }
    int main()
    {
        ios::sync_with_stdio(false);
        cout.tie(NULL);
        n=read();
        Len=(n+1)/2-1;
        for(res i=1;i<=Len;i++)f[1][i]=1;
        for(res i=1;i<=n;i++)sum[1][i]=sum[1][i-1]+f[1][i];
        for(int i=2; i<=4; i++)
            for(int j=1; j<=n; j++)
            {
                int k=min(j,Len);
                f[i][j]=sum[i-1][j-1]-sum[i-1][max(j-k-1,0)];
                sum[i][j]=sum[i][j-1]+f[i][j];
            }
            cout<<f[4][n];
        }
     
  • 相关阅读:
    InSAR 大气校正数据 GACOS
    java通用的方法整理
    Jquery实现select左右栏的添加移除
    kendo ui之grid列表
    kendo-ui学习笔记(一)
    kendo-ui学习笔记——题记
    chrome driver驱动地址
    适合引入缓存的业务及影响
    个人测试方法论202108
    Redis缓存
  • 原文地址:https://www.cnblogs.com/CXYscxy/p/11027663.html
Copyright © 2011-2022 走看看