• 51nod1674:区间的价值2(分治,利用&和|的收敛性)


    lyk拥有一个区间。

    它规定一个区间的价值为这个区间中所有数and起来的值与这个区间所有数or起来的值的乘积。
    例如3个数2,3,6。它们and起来的值为2,or起来的值为7,这个区间对答案的贡献为2*7=14。
    现在lyk有一个n个数的序列,它想知道所有n*(n+1)/2个区间的贡献的和对1000000007取模后的结果是多少。
     
    例如当这个序列为{3,4,5}时,那么区间1,11,1,1,21,2,1,31,3,2,22,2,2,32,3,3,33,3的贡献分别为9,0,0,16,20,25。

    Input第一行一个数n(1<=n<=100000)。 
    接下来一行n个数ai,表示这n个数(0<=ai<=10^9)。Output一行表示答案。Sample Input

    3
    3 4 5

    Sample Output

    70

    题意:求所有区间的&值乘|值。

    思路:分治,利用这两个逻辑运算的收敛性,用map记录相应个数,然后累加即可。

    (和前面利用gcd的收敛性分治的一样的。

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    const int maxn=100010;
    const int Mod=1000000007;
    ll ans;
    ll a[maxn],And[maxn],Or[maxn]; 
    map<pair<ll,ll>,ll>mp;
    map<pair<ll,ll>,ll>::iterator it;
    void solve(int L,int R)
    {
        if(L>R) return ;
        int Mid=(L+R)>>1; mp.clear();
        And[Mid]=a[Mid]; Or[Mid]=a[Mid];
        mp[make_pair(And[Mid],Or[Mid])]++;
        for(int i=Mid-1;i>=L;i--){
            And[i]=And[i+1]&a[i];
            Or[i]=Or[i+1]|a[i];
            mp[make_pair(And[i],Or[i])]++;
        }
        for(int i=Mid;i<=R;i++){
            for(it=mp.begin();it!=mp.end();it++)
                ans+=(ll)(And[i]&(*it).first.first)*(Or[i]|(*it).first.second)%Mod*(*it).second%Mod;
        }
        solve(L,Mid-1); solve(Mid+1,R);
    }
    int main()
    {
        int N,i,j;
        scanf("%d",&N);
        for(i=1;i<=N;i++) scanf("%lld",&a[i]);
        solve(1,N);
        printf("%lld
    ",ans);
        return 0;
    }

     小小优化:

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    const int maxn=100010;
    const int Mod=1e9+7;
    int a[maxn],And[maxn],Or[maxn]; ll ans;
    map<pair<int,int>,int>mp,tp;
    map<pair<int,int>,int>::iterator it1,it2;
    void solve(int L,int R)
    {
        if(L>R) return ;
        int Mid=(L+R)>>1; 
        mp.clear(); tp.clear();
        And[Mid]=a[Mid]; Or[Mid]=a[Mid];
        mp[make_pair(And[Mid],Or[Mid])]++;
        for(int i=Mid-1;i>=L;i--){
            And[i]=And[i+1]&a[i];
            Or[i]=Or[i+1]|a[i];
            mp[make_pair(And[i],Or[i])]++;
        }
        tp[make_pair(And[Mid],Or[Mid])]++;
        for(int i=Mid+1;i<=R;i++){
            And[i]=And[i-1]&a[i]; Or[i]=Or[i-1]|a[i];
            tp[make_pair(And[i],Or[i])]++;
        }
        for(it1=mp.begin();it1!=mp.end();it1++)
         for(it2=tp.begin();it2!=tp.end();it2++)
          ans=(ans+(ll)((*it1).first.first&(*it2).first.first)*((*it1).first.second|(*it2).first.second)%Mod*(*it1).second*(*it2).second)%Mod;
        solve(L,Mid-1); solve(Mid+1,R);
    }
    int main()
    {
        int N,i,j;
        scanf("%d",&N);
        for(i=1;i<=N;i++) scanf("%d",&a[i]);
        solve(1,N);
        printf("%lld
    ",ans);
        return 0;
    }
  • 相关阅读:
    动态规划
    nginx访问静态资源403
    转)服务器CPU占用100%的问题排查
    linux下脚本设置开机自启服务
    在蓝鲸标准运维上进行原子开发
    Django model数据排序
    Mac tar压缩命令,去除隐藏文件
    vue 简单的分页功能实现二
    vue 简单的分页功能实现一
    安装 libmagic in Mac OS (for Python-magic)
  • 原文地址:https://www.cnblogs.com/hua-dong/p/9185351.html
Copyright © 2020-2023  润新知