Live2d Test Env

牛客NOIP暑期七天营-提高组3

-----------今天是被打爆的一天,T3就是用正解做的,但是好像zz了,只得了30分。-----------------

----------------   T1由于没判不合法的情况,也只有15分---------------------

 ---------------------果然是一个拿不到noip一等奖的人----------------------------

----------------------------毕竟noip都准备改名了?-------------------------

 

 

A:破碎的矩阵。

题意:给出N,M,表示有N*M的矩阵,然后给定每一行的异或和,每一列的异或和,求方案数。

思路:如果合法,方案数是pow(2,(N-1)*(M-1)),这个很好想,因为你确定了一个N*M的左上方(N-1)*(M-1)的矩阵后,最后一行一列可以反推,是唯一的。 不合法的情况是,异或和不为0;

#include<bits/stdc++.h>
#define ll long long
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=2000010;
int ans,N,M,Mod; ll x,a[maxn],b[maxn];
int qpow(int base,int num)
{
    int res=1; while(num){
        if(num&1) res=1LL*res*base%Mod;
        num>>=1; base=1LL*base*base%Mod;
    }return res;
}
void solve(int t)
{
    int res=qpow(qpow(qpow(2,N-1),M-1),t);
    ans=1LL*res%Mod%Mod;
}
int main()
{
    int T; scanf("%d",&T);
    while(T--){
        ll xxx=0;
        scanf("%d%d%lld%d",&N,&M,&x,&Mod);
        rep(i,1,N) scanf("%lld",&a[i]),xxx^=a[i];
        rep(i,1,M) scanf("%lld",&b[i]),xxx^=b[i];
        if(xxx) puts("0");
        else {
           int t=0;
           rep(i,0,60) if(x&(1LL<<i)) t++;
           solve(t);
           printf("%d\n",ans);
        }
    }
    return 0;
}
View Code

 

B:点与面。

题意:求W的个数。

思路:裸题,三次BIT即可。

#include<bits/stdc++.h>
#define ll long long
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=500010;
const int Mod=998244353;
int a[maxn],b[maxn],tot;
ll L[maxn],R[maxn],ans,sum[maxn],res[maxn];
ll query(int x){ int res=0;while(x){ (res+=sum[x])%=Mod; x-=(-x)&x;} return res;}
void add(int x,ll y){ while(x<=tot){ sum[x]+=y; if(sum[x]>=Mod) sum[x]-=Mod; x+=(-x)&x;} }
int main()
{
    int N; scanf("%d",&N);
    rep(i,1,N) scanf("%d",&a[i]),b[i]=a[i];
    sort(b+1,b+N+1);  tot=unique(b+1,b+N+1)-(b+1);
    rep(i,1,N) a[i]=lower_bound(b+1,b+tot+1,a[i])-b;
    rep(i,1,N) L[i]=i-1-query(a[i]),add(a[i],1);

    rep(i,1,tot) sum[i]=0;
    for(int i=N;i>=1;i--) R[i]=N-i-query(a[i]),add(a[i],1);

    rep(i,1,tot) sum[i]=0;
    rep(i,1,N) res[i]=1;
    rep(i,1,N) (res[i]*=query(a[i]-1))%=Mod,add(a[i],L[i]);

    rep(i,1,tot) sum[i]=0;
    for(int i=N;i>=1;i--) (res[i]*=query(a[i]-1))%=Mod,add(a[i],R[i]);

    rep(i,1,N) ans+=res[i];
    printf("%lld\n",ans%Mod);
    return 0;
}
View Code

 

C:信息传递

题意: Venn的班级有n个人,他们的座位是首尾相连呈环形的。
如果第i个人得到了Venn的雀魂消息,下一秒就会告诉他左边的Li个人,和右边的Ri个人
注意:由于他们是一个环形,第1个人的左边一个人是第n个人,第n个人的右边一个人是第1个人。
Venn为了防止自己掉分的惨案被大家知道,他想知道对于每一个人,如果消息从他这里传播,需要多久整个班级就会知道。

思路:一眼就可以想到做法,由于ans会比较大,所以倍增。 dp[i][j]表示从i出发,经过1<<j妙,最左到哪里,dp[i][j]=min(L[dp[i][j-1]]...L[i]),区间更新, 所以每一层用线段树优化。

但是我只得了30分。 是因为有个wa点。 就是可能消息不是单方向传递的,所以左右转移要同时进行。 比如1先向右传递到2号学生,2号学生的Li非常的小,那么消息就传到很左边了。

#include<bits/stdc++.h>
#define pii pair<int,int>
#define f first
#define s second
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=300010;
const int inf=1e9;
int l[maxn],r[maxn],a[maxn][18],b[maxn][18],Mn[maxn<<2][18],Mx[maxn<<2][18];
void build(int Now,int L,int R,int p)
{
    if(L==R) {
        Mx[Now][p]=b[L][p];
        Mn[Now][p]=a[L][p];
        return ;
    }
    int Mid=(L+R)>>1;
    build(Now<<1,L,Mid,p);
    build(Now<<1|1,Mid+1,R,p);
    Mx[Now][p]=max(Mx[Now<<1][p],Mx[Now<<1|1][p]);
    Mn[Now][p]=min(Mn[Now<<1][p],Mn[Now<<1|1][p]);
}
pii query(int Now,int L,int R,int l,int r,int p)
{
    if(l<=L&&r>=R) return pii{ Mx[Now][p],Mn[Now][p]};
    int Mid=(L+R)>>1; pii res,tmp;
    res.f=-inf,res.s=inf;
    if(l<=Mid) {
        tmp=query(Now<<1,L,Mid,l,r,p);
        res.f=max(res.f,tmp.f);
        res.s=min(res.s,tmp.s);
    }
    if(r>Mid) {
        tmp=query(Now<<1|1,Mid+1,R,l,r,p);
        res.f=max(res.f,tmp.f);
        res.s=min(res.s,tmp.s);
    }
    return res;
}
int main()
{
    int N,M; scanf("%d",&N); M=3*N;
    rep(i,1,N) scanf("%d",&l[i]),l[i+N]=l[i+N+N]=l[i];
    rep(i,1,N) scanf("%d",&r[i]),r[i+N]=r[i+N+N]=r[i];
    if(N==1){
        puts("0");
        return 0;
    }
    rep(i,1,M) a[i][0]=max(1,i-l[i]);
    rep(i,1,M) b[i][0]=min(M,i+r[i]);
    build(1,1,M,0);
    rep(j,1,17) {
        rep(i,1,M){
            pii t=query(1,1,M,a[i][j-1],b[i][j-1],j-1);
            b[i][j]=t.f;
            a[i][j]=t.s;
        }
        build(1,1,M,j);
    }
    rep(i,1,N) {
        int res=0,L=N+i,R=N+i;
        for(int j=17;j>=0;j--){
            pii t=query(1,1,M,L,R,j);
            int tL=t.s,tR=t.f;
            if(tR-tL<N-1) R=tR,L=tL,res+=(1<<j);
        }
        printf("%d ",res+1);
    }
    return 0;
}

 

posted @ 2019-08-21 18:04  nimphy  阅读(278)  评论(0编辑  收藏  举报