zoukankan      html  css  js  c++  java
  • 排列组合或容斥原理

    题目链接:https://vjudge.net/contest/237052#problem/H

    Here we go!
    Let's define the diversity of a list of numbers to be the difference between the largest and smallest number in the list.
    For example, the diversity of the list (1, -1, 2, 7) = 7 - (-1) = 8.
    A substring of a list is considered a non-empty sequence of contiguous numbers from the list. For example, for the list (1,3,7), the substrings are (1), (3), (7), (1,3), (3,7), (1,3,7). A subsequence of a list is defined to be a non-empty sequence of numbers obtained by deleting some elements from the list. For example, for the list (1,3,7), the subsequences are (1), (3), (7), (1,3), (3,7), (1,7), (1,3,7).
    Given a list of length N find the number of substrings and subsequences in this list with the maximum diversity. If a substring/subsequence having maximum diversity occurs multiple times in the list, each of its occurances adds towards the answer.   And tell Harry Potter your answer.
    Input (STDIN):
    The first line contains T, the number of test cases. Then follow T test case blocks.
    Each blocks starts with the first line containing the number N.
    The second line contains a list of numbers in this list.
    Output (STDOUT):
    For each test case, output the number of substrings and the number of subsequences in this list with the maximum diversity.
    Since the answers maybe very large, output them modulo 1000000007.
    Constraints:
    T <= 10
    N <= 100,000
    Each number in the list is between 1 and 100,000 inclusive.
    Time Limit: 2 s
    Memory Limit: 32 MB
    Sample Input:
    3
    3
    1 2 3
    4
    1 4 3 4
    3
    3 2 1
    Sample Output:
    1 2
    3 6
    12

    Enough with this Harry Potter, please! What are we, twelve-year olds?  Let's get our teeth into some real pumpkin pasties -- oops, programming problems!

    Here we go!

    Let's define the diversity of a list of numbers to be the difference between the largest and smallest number in the list.

    For example, the diversity of the list (1, -1, 2, 7) = 7 - (-1) = 8.

    A substring of a list is considered a non-empty sequence of contiguous numbers from the list. For example, for the list (1,3,7), the substrings are (1), (3), (7), (1,3), (3,7), (1,3,7). A subsequence of a list is defined to be a non-empty sequence of numbers obtained by deleting some elements from the list. For example, for the list (1,3,7), the subsequences are (1), (3), (7), (1,3), (3,7), (1,7), (1,3,7).

    Given a list of length N find the number of substrings and subsequences in this list with the maximum diversity. If a substring/subsequence having maximum diversity occurs multiple times in the list, each of its occurences adds towards the answer.   And tell Harry Potter your answer

    Input (STDIN):

    The first line contains T, the number of test cases. Then follow T test case blocks.

    Each blocks starts with the first line containing the number N.

    The second line contains a list of numbers in this list.

    Output (STDOUT):

    For each test case, output the number of substrings and the number of subsequences in this list with the maximum diversity.

    Since the answers maybe very large, output them modulo 1000000007.

    Constraints:

    T <= 10

    N <= 100,000

    Each number in the list is between 1 and 100,000 inclusive.

    Sample Input:

    3

    3

    1 2 3

    4

    1 4 3 4

    3

    3 2 1

    Sample Output:

    1 2

    3 6

    1 2

     题目大意:输入t,t组测试数据,输入n,有n个数,判断两个不同的字符串和序列串的标准是最大值减最小值不同,字符串必须是连续的,序列串可以不连续

    问你有多少个最大的字符串和序列串

    个人思路:因为所求一定是最大值减最小值,所以先把最大值和最小值记录下来。先看字符串怎么求,看下面例子

    这是一个公式:sum=sum+min(t1,t2),t1,t2是最小最大值的下标,会有更新,刚开始都赋值为0

    2 1 4 3 2 1   min=1,max=4,t1=0,t2=0;

    i=1, t1=0,t2=0,sum=min(0,0)+sum=0;

    i=2, t1=2,t2=0,sum=min(2,0,)+sum=0;

    i=3, t1=2,t2=3,sum=min(2,3)+sum=2,有2 1 4和1 4

    i=4, t1=2,t2=3,sum=min(2,3)+sum=4, 有2 1 4 3和1 4 3

    i=5, t1=2,t2=3,sum=min(2,3)+sum=6,有2 1 4 3 2和1 4 3 2 

    i=6, t1=6,t2=3,sum=min(6,3)+sum=9,有2 1 4 3 2 1和1 4 3 2 1 和4 3 2 1

    那么我们来看为什么会有这个公式呢,加上本身就不用多说了,那么为什么是加上min(t1,t2)呢,因为从后面每增加一个数,都可以在第一个到min(t1,t2)个数开始到末尾

    都是一个字符串,所以增加的就是min(t1,t2)

    然后要求序列串,有两种求法,一种是排列组合,还要一种是容斥原理。需要算出有多少个最大值和最小值

    假设最大值max_num个,最小值min_num个,总共有n个

    排列组合的公式是:(2^min_num-1)*(2^max_num-1)*(2^(n-min_num-max_num)),为什么是这样,自己想一下,就能清楚

    容斥原理的公式是:2^n-2^(n-min_num)-2^(n-max_num)+2^(n-min_num-max_num)

    还有这题很坑,不能用I64d,原因我也不清楚,检查了很久,把输入输出改一下就过了,气气气·······

    看代码

    #include<iostream>
    #include<stdio.h>
    #include<string.h>
    #include<cmath>
    #include<math.h>
    #include<algorithm>
    #include<set>
    typedef long long ll;
    using namespace std;
    const ll mod=1e9+7;
    #define INF 0x3f3f3f
    ll quickpow(ll a,ll b)
    {
        //a的b次方
        ll res=a,ans=1;
        while(b)
        {
            if(b&1)
            {
                ans=ans*res%mod;
                res=res*res%mod;
            }
            else
                res=res*res%mod;
            b=b>>1;
        }
        return ans;
    }
    int main()
    {
        ll t;
        ll a[100050];
        scanf("%lld",&t);
        //cin>>t;
        while(t--)
        {
            ll n,mi=INF,ma=-1,l=0,r=0,ans=0,ans1=0,min_num=0,max_num=0;//l代表最小值的下标,r代表最大值的下标
            scanf("%lld",&n);
            //cin>>n;
            for(int i=1;i<=n;i++)
            {
                scanf("%lld",&a[i]);
               // cin>>a[i];
                if(a[i]>ma)
                    ma=a[i];
                if(a[i]<mi)
                    mi=a[i];
            }
            if(mi==ma)
            {
                ans=n*(n+1)/2%mod;
                ans1=quickpow(2,n)-1;
                printf("%lld %lld
    ",ans,ans1);
               //cout<<ans<<' '<<ans1<<endl;
                continue;
            }
            for(int i=1;i<=n;i++)
            {
                if(a[i]==mi)
                {
                    l=i;
                    min_num++;//最小值个数
                }
                if(a[i]==ma)
                {
                    r=i;
                    max_num++;//最大值个数
                }
                ans=(ans+min(l,r))%mod;//子串个数
            }//注意这里要时刻%mod,不这样就wa,可能会爆
            ans1=(quickpow(2,min_num)-1)%mod*(quickpow(2,max_num)-1)%mod*(quickpow(2,n-min_num-max_num))%mod;
           // ans1=(quickpow(2,n)-quickpow(2,n-min_num)-quickpow(2,n-max_num)+quickpow(2,n-min_num-max_num))%mod;
            if(ans1<0)
                ans1=ans1+mod;
            printf("%lld %lld
    ",ans,ans1);
            //cout<<ans<<' '<<ans1<<endl;
        }
        return 0;
    }
    当初的梦想实现了吗,事到如今只好放弃吗~
  • 相关阅读:
    题解-FJOI2014 树的重心
    题解-CF1307G Cow and Exercise
    题解-SHOI2005 树的双中心

    【转载】SVN使用教程总结
    Fastcgi、CGI 是什么
    通过js或jq增加的代码,点击事件或其他一些事件不起作用时
    js闭包讲解
    PHP 程序员危机(转载)
    浏览器 User-Agent相关知识
  • 原文地址:https://www.cnblogs.com/caijiaming/p/9309349.html
Copyright © 2011-2022 走看看