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

分析

大佬说看样例就像和卷积有关。

把题目化简成a*x=b,这是个xor的FWT。

FWT的讲解请看:https://www.cnblogs.com/cjyyb/p/9065615.html

那么要求的是x,所以我们得逆着来,则对b进行IFWT,对a FWT,然后c=b/a,于是x=FWT(c).

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
#include <ctime>
#include <vector>
#include <queue>
#include <map>
#include <stack>
#include <set>
#include <bitset>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define ms(a, b) memset(a, b, sizeof(a))
#define pb push_back
#define mp make_pair
#define pii pair<int, int>
#define IOS ios::sync_with_stdio(0);cin.tie(0);
#define random(a, b) rand()*rand()%(b-a+1)+a
#define pi acos(-1.0)
const ll INF = 0x3f3f3f3f3f3f3f3fll;
const int inf = 0x3f3f3f3f;
const int maxn = 3e5+10;
const int maxm = 1e5+10;
const int mod = 1e9+7;
ll qpow(ll a,ll b){
    ll res=1;
    while(b){
        if(b&1) res=res*a%mod;
        b>>=1;
        a=a*a%mod;
    }
    return res;
}
ll inv = 500000004;
void IFWT(int 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++){
                int x = a[i+j],y=a[i+j+d];
                a[i+j]=(x+y)%mod*inv%mod;
                a[i+j+d]=(x-y+mod)%mod*inv%mod;
            }
}

void FWT(int 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++){
                int x = a[i+j],y=a[i+j+d];
                a[i+j]=(x+y)%mod;
                a[i+j+d]=(x-y+mod)%mod;
            }
}
int a[maxn],b[maxn];
int main(){
#ifdef LOCAL
    freopen("in.txt", "r", stdin);
//    freopen("output.txt", "w", stdout);
#endif
    int n;
    scanf("%d",&n);
    for(int i=0;i<n;i++) scanf("%d",&a[i]);
    for(int i=0;i<n;i++) scanf("%d",&b[i]);
    FWT(a,n);
    IFWT(b,n);
    for(int i=0;i<n;i++) a[i]=b[i]*qpow(a[i],mod-2)%mod;
    FWT(a,n);
    for(int i=0;i<n;i++) cout<<a[i]<<endl;
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/fht-litost/p/9508897.html