• 【2018沈阳现场赛I】Distance Between Sweethearts


    题意

    分析

    看似是期望问题,但是没有权重,就是求平均值,而答案要求乘上方案总数,所以 这是一个计数问题

    考虑max,若三个绝对值分别为(x,y,z),则max = max(x,y,z)

    distance = max ^ Ib ^ (Ib+x) ^ Ab ^ (Ab + y) ^ Gb ^ (Gb + z) 

    我们统计出每种Ib^Ig ( |Ib - Ig| ≤ x ) 的方案数,同理其他属性也是,总共产生三个数组

    根据乘法原理,我们可以求得 k = Ib ^ (Ib+x) ^ Ab ^ (Ab + y) ^ Gb ^ (Gb + z) 的方案数为∑ (cnt_I[ Ib ^ (Ib+x) ] * cnt_A[Ab ^ (Ab + y)] * cnt_G[Gb ^ (Gb + z)]),这里就可以做异或卷积 

    但我们还要统计max,那在max值固定的情况下,也就是x,y,z至少有一个等于一个定值max,这样的方案数如何统计呢?

    考虑容斥,令 某一种方案为Ib ,Ig = (Ib+x), Ab  , Ag =(Ab + y) , Gb ,Gg = (Gb + z)  记作 (x,y,z)

    如果我们计算出来了x<=max && y<=max && z <=max的方案数A,又计算出了x<max && y<max && z <max 的方案数B , 上述的方案数就等于A - B,

    所以可以每次枚举max值的时候,去累加cnt,这样单种元素的绝对值都不超过max

    btw:为什么我自己以前fwt板子挂了啊 TAT ,借鉴了聚聚的板子

    代码

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    
    
    ll IB,AB,GB,IG,AG,GG;
    ll cnt[3][2048];
    ll a[3][2048];
    ll pre[2048];
    ull ans;
    void csh(){
        memset(cnt,0,sizeof(cnt));
        memset(pre,0,sizeof(pre));
    }
    void fwt(ll a[],int n,int v) {
        for(int d=1;d<n;d<<=1) {
        for(int m = d<<1,i=0;i<n;i+=m) {
            for(int j=0;j<d;j++){
            ll x = a[i+j],y = a[i+j+d];
            if(v == 1) a[i+j] = (x+y),a[i+j+d] = (x-y);
            else a[i+j] = (x+y)/2,a[i+j+d] = (x-y)/2;
            }
        }
        }
    }
    int main() {
        ios::sync_with_stdio(false);
        int _,ca=0;cin>>_;
        while(_--) {
        
        cin>>IB>>AB>>GB>>IG>>AG>>GG;
        csh();
        ans=0;
        for(int maxx = 0;maxx <=2000;maxx++) {
        //    cout<<"MAX = "<<maxx<<endl;
            for(int i=0;i<=IB&&i+maxx<=IG;i++) cnt[0][i^(i+maxx)]++;
            if(maxx>0) for(int i=0;i<=IG&&i+maxx<=IB;i++)cnt[0][i^(i+maxx)]++;
            for(int i=0;i<=AB&&i+maxx<=AG;i++) cnt[1][i^(i+maxx)]++;
            if(maxx>0) for(int i=0;i<=AG&&i+maxx<=AB;i++)cnt[1][i^(i+maxx)]++;
            for(int i=0;i<=GB&&i+maxx<=GG;i++) cnt[2][i^(i+maxx)]++;
            if(maxx>0) for(int i=0;i<=GG&&i+maxx<=GB;i++)cnt[2][i^(i+maxx)]++;
            for(int i=0;i<2048;i++) a[0][i] = cnt[0][i],a[1][i] = cnt[1][i],a[2][i]=cnt[2][i];
            fwt(a[0],2048,1);
            fwt(a[1],2048,1);
            fwt(a[2],2048,1);
            for(int i=0;i<2048;i++) {
            a[0][i] = a[0][i] * a[1][i] * a[2][i];
            }
            fwt(a[0],2048,-1);
            for(int i=0;i<2048;i++) {
            ans+=(a[0][i] - pre[i])*(i^maxx);    
            pre[i] = a[0][i];
            }
        }
        cout<<"Case #"<<++ca<<": "<<ans<<endl;
        }
    }
  • 相关阅读:
    自定义函数
    取小数的有效值函数
    数据恢复bak
    脚本启动windows服务
    创建表
    PostgreSQL和SQL SERVER的数据库差异
    vs2019莫名自动退出调试状态
    postgresql 设置调试
    Google Web字体,让你的网页更迷人
    翻译:观察者模式—使用JavaScript实现
  • 原文地址:https://www.cnblogs.com/greenty1208/p/9992883.html
Copyright © 2020-2023  润新知