ZOJ 3872 Beauty of Array&&ZOJ 3870 Team Formation

3872链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3872

题目大意:给你n个数,问所有的连续的子序列中的所有元素的和(子序列中有相同元素只计算一次)(n<100000)。

即若序列为1  2  3,则组成1,2,3,1 2,2 3,1 2 3,和为20;

若序列为1 2 2,则组成1,2,2,1 2,2 2,1 2 2,和为13;

解题思路:求不重复的序列和很简单,关键是去重。

现在看一个序列: 3  4  7  6   4 ;如图中的4,

我们记录每个元素上一次出现的位置2,当下一次到 5  时再碰到这个元素,则在区间[ 3,5 ]这段区间的子序列的和需要当前  蓝色的4 这个元素,在包含[ 1 ,2]这个区间内的所有数的子序列不用计算第  后面的4  这个元素,但是 虽然不用计算  后面的4 ,但前面4个元素的所有子序列的和还是要计算,只是不包括最后的4.

令dp[ i ]表示前i个元素(包含i)的所有子序列的和,则  dp[ i ]=dp[ i-1 ]+(n-mp[  s[i]  ])*s[i];其中mp[ s[i] ]表示s[ i ]上次出现的位置;最后用sum计算总的和就行了。

当然 dp[ i ] 可以用dp表示,因为像0/1背包的空间优化类似。

代码如下:

#include<cstdio>
#include<cstring>
using namespace std;
#define LL long long
#define M 1000005
int mp[M];
int main()
{
    int t,n,a;
    scanf("%d",&t);
    while(t--)
    {
        LL sum=0;
        memset(mp,0,sizeof(mp));
        scanf("%d",&n);
        LL dp=0;
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a);
            dp=dp+(i-mp[a])*a;
            mp[a]=i;
            sum+=dp;
        }
        printf("%lld\n",sum);
    }
}

3870链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3870

题目大意:给你n个数,问满足  两个数异或之后的值 比这两个数都大的 组合有多少种?(n<100000)

解题思路:对于这样一些数:                          1        (1)

1 0        (2)

1 1        (3)

1 0 0       (4)

1 0 1        (5)

1 1 0        (6)

对于上面的数我们发现,其二进制的最高位肯定为1,1^1=0,那么位数相同的肯定不能组合,又发现    只有当某一位出现0时  和   上面同一位出现1的数组合  才有可能增大,为什么说有可能呢?比如3  和6 的组合,最低位为0^1=1是增大的,但次位为1^1=0减小,所以不符合;怎么才一定符合呢?那就是和当前位组合后,较小数的前面所有位(高位)都为0,那么解法就有了,先对所有的数排序,对每个数二进制分解,遍历每一位,当第i位为1时,s[ len ][ i ]++,其中len表示当前这个数的二进制长度,s[
len ][ i ]表示长度为len的数中第i位为1的数的个数;当第i位为0时,查找二进制长度为i的所有数中第i位为1的数的个数,之前遍历的时候已经预处理过了,直接加上就行了。

代码如下:

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
int s[35][35];
int d[100005];
int bin(int x)///某个数的二进制分解位数
{
    int cnt;
    for(int i=1;i<32;i++)
    if((1<<i)-1>=x)
        {cnt=i;return cnt;}
}
int main()
{
    int t,n;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        for(int i=0;i<n;i++)
            scanf("%d",&d[i]);
        sort(d,d+n);
        memset(s,0,sizeof(s));
        int ans=0;
        for(int i=0;i<n;i++)
        {
            int cnt=bin(d[i]);
            int k=1;
            while(d[i])///二进制分解
            {
                int r=d[i]%2;
                if(r==1) s[cnt][k]++;
                else ans+=s[k][k];
                k++;
                d[i]/=2;
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}
时间: 2024-10-01 01:14:48

ZOJ 3872 Beauty of Array&&ZOJ 3870 Team Formation的相关文章

DP ZOJ 3872 Beauty of Array

题目传送门 1 /* 2 DP:dp 表示当前输入的x前的包含x的子序列的和, 3 求和方法是找到之前出现x的位置(a[x])的区间内的子序列: 4 sum 表示当前输入x前的所有和: 5 a[x] 表示id: 6 详细解释:http://blog.csdn.net/u013050857/article/details/45285515 7 */ 8 #include <cstdio> 9 #include <algorithm> 10 #include <cmath>

ZOJ 3872 Beauty of Array(数学)

Beauty of Array Time Limit: 2 Seconds      Memory Limit: 65536 KB Edward has an array A with N integers. He defines the beauty of an array as the summation of all distinct integers in the array. Now Edward wants to know the summation of the beauty of

ZOJ 3872 Beauty of Array(数学啊)

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5520 Edward has an array A with N integers. He defines the beauty of an array as the summation of all distinct integers in the array. Now Edward wants to know the summation of the beauty

ZOJ 3872 Beauty of Array 连续子序列求和

Edward has an array A with N integers. He defines the beauty of an array as the summation of all distinct integers in the array. Now Edward wants to know the summation of the beauty of all contiguous subarray of the array A. Input There are multiple

ZOJ - 3872 Beauty of Array

题意:给定一个含有N个数的序列S,定义序列的魅力值为序列中不同数字之和,求出该序列所有子序列的魅力值之和. 分析:每个数乘以它出现的次数,求和即可. 如何求每个数出现的次数? 1.对于一个各数字完全不同的序列, eg:3 5 2 6 8 对于5来说,确定其存在于的子序列 (1)其右面,可选0个数字---5  可选1个数字---3 5 (2)其右面,可选0个数字---5  可选1个数字---5 2  可选2个数字---5 2 6        可选3个数字---5 2 6 8 因此,2 * 4 =

位运算 ZOJ 3870 Team Formation

题目传送门 1 /* 2 题意:找出符合 A^B > max (A, B) 的组数: 3 位运算:异或的性质,1^1=0, 1^0=1, 0^1=1, 0^0=0:与的性质:1^1=1, 1^0=0, 0^1=0, 0^0=0: 4 假设A < B,一定要满足B的最高位对应A的值是0,这样才可能>B(即0^1=1): 5 然后比赛时假设A的极限是类似0111111的情况,最后假设有误: 6 题解是先把每个数最高位(1)的位置统计个数,1<<4 的意思是 000010000:

ZOJ 3870 Team Formation

题目链接: http://www.icpc.moe/onlinejudge/showProblem.do?problemCode=3870 题解: 如果x xor y>max(x,y),那么就会有x和y的最高位不同(二进制表示),并且对于最高位小的那个数的最高位的位置,最高位大的那个数在相同的位置应为0. 代码: 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 using namespac

ZOJ 3870 Team Formation(位运算)

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5518 For an upcoming programming contest, Edward, the headmaster of Marjar University, is forming a two-man team from N students of his university. Edward knows the skill level of each s

Zoj 3842 Beauty of Array

Problem地址:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5520 根据题目的要求,需要算出所有连续子数组的the beauty的总和. 那么要求这个这个总和,刚开始最容易想到的就是这样: for( int i=1; i<=N; i++ ) { for( int j = 1; j<=i; j++ ) { ... //排除重复的数计算总和 } } 这样子的结果实际上是 Time Limit Exceeded 因此采取