牛客网暑期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
",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$,在这卡了好久。
```c++
#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
",(dp[n]+mod)%mod);
return 0;
}
```]