zoukankan      html  css  js  c++  java
  • BZOJ 1800(思维)

    传送门

    题面:

    1800: [Ahoi2009]fly 飞行棋

    Time Limit: 10 Sec  Memory Limit: 64 MB
    Submit: 2267  Solved: 1733
    [Submit][Status][Discuss]

    Description

    给出圆周上的若干个点,已知点与点之间的弧长,其值均为正整数,并依圆周顺序排列。 请找出这些点中有没有可以围成矩形的,并希望在最短时间内找出所有不重复矩形。

    Input

    第一行为正整数N,表示点的个数,接下来N行分别为这N个点所分割的各个圆弧长度

    Output

    所构成不重复矩形的个数

    Sample Input

    8
    1
    2
    2
    3
    1
    1
    3
    3

     

    Sample Output

    3

    HINT

    N<= 20

    题目分析:

        对于这个题目,我们首先需要回忆起一个初中所学过的定理:同弧所对的圆周角=圆心角的一半。

        这就意味着,倘若两个不相交的弧,如果他们的长度相同,则一定有他们弧所对应的弦长相同。

        由此我们可以想到一个最朴素的算法,我们枚举圆上的四个点,判断一下相对的两条边的弧长是否相同即可。两两间的弧长可以通过维护前缀和实现。此时的时间复杂度为O(n^4)。

        但是这个题还是可以把复杂度继续压下来的。

        考虑到题目中要我们求的是矩形,根据矩形在圆内的性质,不难发现,一个矩形是由两条相交的直径构成的。因此倘若我们知道了n个点可以构成的直径的个数,则最终的答案即为C(直径,2)。

        而继续根据同弧所对的圆周角=圆心角的一半,我们知道,一段弧长为直径,当且仅当弧长为周长的一半。因此我们现在只需要枚举两个点,不断判断这两个点是否是直径即可。此时的时间复杂度为O(n^2)。

    代码:

    //O(n^4)
    #include <bits/stdc++.h>
    #define maxn 25
    using namespace std;
    int sum[maxn];
    int a[maxn];
    int main()
    {
        int n;
        //freopen("in.txt","r",stdin);
        scanf("%d",&n);
        int tot=0;
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
            sum[i]=sum[i-1]+a[i];
        }
        int res=0;
        for(int a=1;a<=n;a++)
        for(int b=a+1;b<=n;b++)
        for(int c=b+1;c<=n;c++)
        for(int d=c+1;d<=n;d++){
            if((sum[b]-sum[a]==sum[d]-sum[c])&&(sum[n]-sum[d]+sum[a]==sum[c]-sum[b]))
            res++;
        }
        cout<<res<<endl;
    }
    //O(n^2)
    #include <bits/stdc++.h>
    #define maxn 25
    using namespace std;
    int sum[maxn];
    int a[maxn];
    int main()
    {
       // freopen("in.txt","r",stdin);
        int n;
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
            sum[i]=sum[i-1]+a[i];
        }
        int cnt=0;
        for(int i=1;i<=n;i++){
            for(int j=i+1;j<=n;j++){
                if(sum[j]-sum[i]==sum[n]/2) cnt++;
            }
        }
        cout<<cnt*(cnt-1)/2<<endl;
    }
    
  • 相关阅读:
    LeetCode 1356. 根据数字二进制下1的数目排序
    Ubuntu LaTeX 中文环境配置 与 VSCode LaTeX Workshop
    LeetCode 57. 插入区间
    VSCode Ubuntu下调试失败 无法打开 libc-start.c raise.c等
    LeetCode 30. 串联所有单词的子串
    日期处理函数
    Stream 和 byte[] 之间的转换
    Math.Round {实现四舍五入的小技巧}
    重写alert弹窗
    js轮播图
  • 原文地址:https://www.cnblogs.com/Chen-Jr/p/11007183.html
Copyright © 2011-2022 走看看