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

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


A. Circulant Matrix

做法:看到下标 \(xor\) 这种情况就想 \(FWT\),可是半天没思路,于是放弃了。。其实这个 \(n\) 疯狂暗示啊。设未知数向量为 \(x\),列一下方程组就可以发现有: \[b[k] = \sum_{i \oplus j= k} a[i]·x[j]\] 做法就显然了吧,把\(a\)\(b\)分别\(FWT\),对应相除然后反变换即可。表示前天才学的\(FWT\),就不会使了。。

#include <bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;++i)
typedef long long ll;
const int mod = 1e9+7;
const int N = 262144+10;
using namespace std;
inline int add(int x,int y) {
    x+=y;
    if(x>=mod)x-=mod;return x;
}
inline int sub(int x,int y) {
    x-=y;
    if(x<0)x+=mod;return x;
}
int n;
ll a[N],b[N],inv2;
ll q_pow(ll a,ll b) {
    ll ans=1;
    while(b) {
        if(b&1) ans=(ans*a)%mod;
        a=(a*a)%mod;
        b>>=1;
    }
    return ans;
}
void FWT_xor(ll a[],int n,int on) {
    for(int i=1;i<n;i<<=1) {
        for(int j=0;j<n;j+=(i<<1)) {
            for(int k=0;k<i;++k) {
                ll u=a[j+k], t=a[j+k+i];
                a[j+k]=add(u,t); a[j+k+i]=sub(u,t);
                if(on==-1) {
                    a[j+k]=(ll)a[j+k]*inv2%mod;
                    a[j+k+i]=(ll)a[j+k+i]*inv2%mod;
                }
            }
        }
    }
}
int main() {
    scanf("%d",&n);
    inv2 = q_pow(2,mod-2);
    rep(i,0,n-1) scanf("%lld",&a[i]);
    rep(i,0,n-1) scanf("%lld",&b[i]);
    FWT_xor(a,n,1);
    FWT_xor(b,n,1);
    rep(i,0,n-1) a[i]=(b[i]*q_pow(a[i],mod-2))%mod;
    FWT_xor(a,n,-1);
    rep(i,0,n-1) printf("%lld\n",a[i]);
    return 0;
}

E. Music Game

做法:签到题。\(dp[i]\) 表示前i个位置的答案,转移就有:1)当前这一位是 \(0\) 2)当前这一位到位置 \(j\) 都是\(1\),位置\(j-1\)\(0\),直接dp即可。
\[dp[i] = dp[i-1]·(1-p[i]) + i^m·\prod_{j=1}^ip[i] + (i-1)^m·\prod_{j=2}^ip[i]·(1-p[1]) + \sum_{j=3}^i ((i-j+1)^m + dp[j-2])·\prod_{k=j}^i p[k]·(1-p[j-1])\]要注意区间的概率需要判\(0\),在这卡了好久。

#include <bits/stdc++.h>
#define rep(i,a,b) for(ll i=a;i<=b;++i)
typedef long long ll;
const ll mod = 1e9 + 7;
const int N = 1100;
using namespace std;
ll q_pow(ll a,ll b) {
    ll ans = 1;
    while(b) {
        if(b&1) ans=(ans*a)%mod;
        a=(a*a)%mod;
        b>>=1;
    }
    return ans;
}
ll INV(ll x) {
    return q_pow(x,mod-2);
}
ll n,m,p[N],inv1,dp[N],PP[N],s0[N];
ll P(int l,int r) {
    ll ans=0;
    if(s0[r]-s0[l-1]==0) return PP[r]*INV(PP[l-1])%mod;
    return 0;
}
int main() {
    scanf("%lld%lld",&n,&m);
    inv1=q_pow(100LL,mod-2);
    rep(i,1,n) scanf("%lld",&p[i]),(p[i]*=inv1)%=mod;
    //cal();
    int tt = 1,cc=0;
    while(p[tt]==0&&tt<=n)++tt;
    for(int i=tt;i<=n;++i) p[++cc]=p[i];
    n=cc;
    PP[0]=1;
    PP[1]=p[1];
    s0[1]=(p[1]==0);
    rep(i,2,n) {
        if(p[i]) PP[i]=(PP[i-1]*p[i])%mod;
        else PP[i]=PP[i-1];
        s0[i]=(s0[i-1])+(p[i]==0);
    }
    dp[1] = p[1];
    rep(i,2,n) {
        dp[i] = (dp[i-1]*(1-p[i]+mod))%mod;
        dp[i] += ((q_pow(i-1LL,m)*P(2,i))%mod*(1-p[1]+mod))%mod;
        dp[i] %= mod;
        dp[i] += (q_pow(i,m)*P(1,i))%mod;
        dp[i] %= mod;
        if(i>2) {
            rep(j,3,i) {
                dp[i] += (((q_pow(i-j+1,m)+dp[j-2])%mod*P(j,i))%mod*(1-p[j-1]+mod))%mod;
                dp[i] %= mod;
            }
        }
        dp[i] %= mod;
    }
    dp[n]%=mod;
    printf("%lld\n",(dp[n]+mod)%mod);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/RRRR-wys/p/9489432.html