2018 ACM-ICPC 沈阳站 Problem I. Distance Between Sweethearts FWT

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/fanbaobao829/article/details/83301435
#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ll;
const int maxn=1e4+5;
int UIB,UAB,UGB,UIG,UAG,UGG,I[maxn],A[maxn],G[maxn],pre_op,now_op;
ll temp[maxn],num[2][maxn],res[maxn],ans;
void FWT(ll a[],int n)
{
    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];
                ll y=a[i+j+d];
                a[i+j]=x+y;
                a[i+j+d]=x-y;
                //xor:a[i+j]=x+y,a[i+j+d]=x-y;
                //and:a[i+j]=x+y;
                //or:a[i+j+d]=x+y;
            }
}
void UFWT(ll a[],int n)
{
    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];
                ll y=a[i+j+d];
                a[i+j]=(x+y)>>1;
                a[i+j+d]=(x-y)>>1;
                //xor:a[i+j]=(x+y)/2,a[i+j+d]=(x-y)/2;
                //and:a[i+j]=x-y;
                //or:a[i+j+d]=y-x;
            }
}
void solve(ll a[],ll b[],int n)
{
    FWT(a,n);
    FWT(b,n);
    for(int i=0;i<n;++i)
        a[i]*=b[i];
    UFWT(a,n);
}
void pre_fill(ll a[],int b[],int n)
{
    for(int i=0;i<n;++i)
        a[i]=(ll)b[i];
}
int get_length(int n)
{
    int res=1;
    while(res<=n)
        res<<=1;
    return res;
}
void up_date(int a[],int n,int m,int k)
{
    if(k)
        for(int i=0;i<=n;++i)
        {
            if(i-k>=0)
                ++a[i^(i-k)];
            if(i+k<=m)
                ++a[i^(i+k)];
        }
    else
        a[0]=n+1;
}
void init()
{
    ans=now_op=pre_op=0;
    memset(I,0,sizeof(I));
    memset(A,0,sizeof(A));
    memset(G,0,sizeof(G));
    memset(res,0,sizeof(res));
    memset(num,0,sizeof(num));
}
int main()
{
    //freopen("test.in","r",stdin);
    //freopen("test.out","w",stdout);
    int t,n,m,cas=1;
    scanf("%d",&t);
    while(t--&&scanf("%d%d%d%d%d%d",&UIB,&UAB,&UGB,&UIG,&UAG,&UGG)!=EOF)
    {
        init();
        if(UIB>UIG)
            swap(UIB,UIG);
        if(UAB>UAG)
            swap(UAB,UAG);
        if(UGB>UGG)
            swap(UGB,UGG);
        n=max(max(UIG,UAG),UGG);
        m=get_length(n);
        for(int i=0;i<=n;++i)
        {
            now_op=pre_op^1;
            up_date(I,UIB,UIG,i);
            up_date(A,UAB,UAG,i);
            up_date(G,UGB,UGG,i);
            pre_fill(num[now_op],I,m);
            pre_fill(temp,A,m);
            solve(num[now_op],temp,m);
            pre_fill(temp,G,m);
            solve(num[now_op],temp,m);
            for(int j=0;j<m;++j)
                res[j^i]+=num[now_op][j]-num[pre_op][j];
            pre_op=now_op;
        }
        for(int i=0;i<m;++i)
            ans+=res[i]*i;
        printf("Case #%d: %lu\n",cas++,ans);
    }
    return 0;
}
/*
10
3 1 2 4 3 3
1 2 1 2 1 3
3 2 5 4 3 5
2000 2000 2000 2000 2000 2000
2000 2000 2000 2000 2000 2000
2000 2000 2000 2000 2000 2000
2000 2000 2000 2000 2000 2000
2000 2000 2000 2000 2000 2000
2000 2000 2000 2000 2000 2000
2000 2000 2000 2000 2000 2000
*/

猜你喜欢

转载自blog.csdn.net/fanbaobao829/article/details/83301435