竞赛讨论区 > 2018牛客网暑期ACM多校训练营(第九场)A
头像
tokitsukaze
编辑于 2018-08-16 19:46
+ 关注

2018牛客网暑期ACM多校训练营(第九场)A




题解:
观察样例感觉是个卷积,然后发现是个xor的FWT。
题意转换成,给个a数组和c数组,求一个b数组,使得a数组和b数组做FWT后的结果为c数组。
然后观察FWT的过程:对a,b数组做FWT,c[i]=a[i]*b[i],然后对c数组做UFWT。
我们把这个过程倒过来:先对c数组做UFWT,然后对a数组做FWT,然后b[i]=c[i]/a[i],最后对b数组做FWT,就把b数组还原了。



代码:

#include <bits/stdc++.h>
using namespace std;
#pragma comment(linker, "/STACK:1024000000,1024000000")
#define mem(a,b) memset((a),(b),sizeof(a))
#define MP make_pair
#define pb push_back
#define fi first
#define se second
#define sz(x) (int)x.size()
#define all(x) x.begin(),x.end()
using namespace __gnu_cxx;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> PII;
typedef pair<ll,ll> PLL;
typedef vector<int> VI;
typedef vector<ll> VL;
void go();
int main(){
    #ifdef tokitsukaze
        freopen("TEST.txt","r",stdin);
    #endif
    go();return 0;
}
const int INF=0x3f3f3f3f;
const ll LLINF=0x3f3f3f3f3f3f3f3f;
const double PI=acos(-1.0);
const double eps=1e-6;
const int MAX=6e5+10;
const ll mod=1e9+7;
/*********************************  head  *********************************/
namespace FWT
{
    ll inv2;
    const ll p=1e9+7;
    ll pow2(ll a,ll b)
    {
        ll res=1;
        while(b)
        {
            if(b&1) res=res*a%p;
            a=a*a%p;
            b>>=1;
        }
        return res;
    }
    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) a[i+j]=(x+y)%p,a[i+j+d]=(x-y+p)%p;
                    else a[i+j]=(x+y)*inv2%p,a[i+j+d]=(x-y+p)%p*inv2%p;
                }
            }
        }
    }
    void XOR(ll *a,ll *b,int n)
    {
        int len;
        for(len=1;len<=n;len<<=1);
        fwt(a,len,0);
        fwt(b,len,0);
        for(int i=0;i<len;i++) a[i]=a[i]*b[i]%p;
        inv2=pow2(2,p-2);
        fwt(a,len,1);
    }
    void XOR_inv(ll *a,ll *b,int n)
    {
        int len;
        for(len=1;len<=n;len<<=1);
        inv2=pow2(2,p-2);
        fwt(a,len,1);
        fwt(b,len,0);
        for(int i=0;i<len;i++) a[i]=a[i]*pow2(b[i]%p,p-2)%p;
        fwt(a,len,0);
    }
};
ll a[MAX],b[MAX];
void go()
{
    int n,i;
    while(read(n))
    {
        for(i=0;i<n;i++) read(b[i]);
        for(i=0;i<n;i++) read(a[i]);
        FWT::XOR_inv(a,b,n);
        for(i=0;i<n;i++) printf("%lld\n",a[i]);
    }
}

全部评论

(0) 回帖
加载中...
话题 回帖

等你来战

查看全部

热门推荐