省选模拟37

连续垫底第五场,希望自己对垫底没有什么感觉,但是还是很伤心,为啥自己突然这么菜

成绩的上下波动一直很厉害,不知道该咋办......

上来看第一题,发现计数不是记少了就是记重了,两个半小时之后弃掉了

然后看第二题,发现只会暴力分,抱着试试看的想法搞了一下逆序对个数发现不对就走了

第三题,一点思路都没有...

T1 小 F 与游戏

也不用说了,我是打表找规律过的...%%%APJifengc

AC_code
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define ull unsigned long long
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
int read(){
    int s=0,t=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')t=-1;ch=getchar();}
    while(isdigit(ch)){s=(s<<1)+(s<<3)+(ch^48);ch=getchar();}
    return s*t;
}
const int N=5e5+5;
const int inf=0x3f3f3f3f3f3f3f3f;
int n,k,mod,ans;
int ksm(int x,int y){
    int ret=1;
    while(y){
        if(y&1)ret=ret*x%mod;
        x=x*x%mod;y>>=1;
    }return ret;
}
int jc[N*2],inv[N*2];
int C(int x,int y){return jc[x]*inv[y]%mod*inv[x-y]%mod;}
signed main(){
    freopen("game.in","r",stdin);
    freopen("game.out","w",stdout);
    n=read();k=read();mod=read();
    jc[0]=1;fo(i,1,2*n)jc[i]=jc[i-1]*i%mod;
    inv[0]=1;inv[2*n]=ksm(jc[2*n],mod-2);
    fu(i,2*n-1,1)inv[i]=inv[i+1]*(i+1)%mod;
    if(k==1){printf("%lld\n",ksm(2,n-2));}
    else if(k==n){printf("%lld\n",C(2*n-2,n-1)*ksm(n,mod-2)%mod);}
    else {printf("%lld\n",ksm(2,n-k-1)*(C(n+k-2,n-1)-C(n+k-2,n)+mod)%mod);}
    return 0;
}

T2 小 Z 与函数

发现交换的是顺序对个数,但是前面的重复数字只计算一次

那么剩下的任务就是看哪些点是需要交换的

这个地方我搞了好久好久,要理解一个思想,就是问题拆分化,如果发现一个问题的两个部分没有关系那么就可以分开计算了

对于每一个位置单独考虑,处理当前位置的时候,这个位置的数是前缀最小值

那么只要这个数后面还有一个比他大的数,那这个位置就需要交换

如果有相同的数,那么我们就接着上一个找到的位置继续向后找就行了

这个是保证一共有至少i个数大于当前这个数,这样就必须向后移动了

AC_code
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
int read(){
    int s=0,t=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')t=-1;ch=getchar();}
    while(isdigit(ch)){s=(s<<1)+(s<<3)+(ch^48);ch=getchar();}
    return s*t;
}
const int N=2e5+5;
const int inf=0x3f3f3f3f3f3f3f3f;
int T,n,a[N],ans,res;
bool vis[N];
struct BIT{
    int tr[N];
    void ins(int x,int v){
        for(int i=x;i<=n;i+=(i&-i))tr[i]+=v;
    }
    int query(int x){
        int ret=0;
        for(int i=x;i;i-=(i&-i))ret+=tr[i];
        return ret;
    }
    int qry(int l,int r){
        return query(r)-query(l-1);
    }
}bit,bic;
int sta[N],top,len[N];
int mn[N],las[N],ps[N],pos[N];
struct XDS{
    #define ls x<<1
    #define rs x<<1|1
    int mx[N*4];
    void pushup(int x){
        mx[x]=max(mx[ls],mx[rs]);
        return ;
    }
    void build(int x,int l,int r){
        if(l==r)return mx[x]=a[l],void();
        int mid=l+r>>1;
        build(ls,l,mid);
        build(rs,mid+1,r);
        pushup(x);return ;
    }
    int query(int x,int l,int r,int ql,int v){
        if(ql>n)return n+1;
        if(ql<=l){
            if(mx[x]<=v)return r+1;
            if(l==r)return r;
            int mid=l+r>>1;
            if(mx[ls]<=v)return query(rs,mid+1,r,ql,v);
            else return query(ls,l,mid,ql,v);
        }
        int mid=l+r>>1,ret=0;
        if(ql<=mid)ret=query(ls,l,mid,ql,v);
        if(!ret||ret==mid+1)ret=query(rs,mid+1,r,ql,v);
        return ret;
    }
    #undef ls
    #undef rs
}xds;
signed main(){
    freopen("function.in","r",stdin);
    freopen("function.out","w",stdout);
    T=read();mn[0]=inf;
    while(T--){
        memset(vis,false,sizeof(vis));
        memset(bit.tr,0,sizeof(bit.tr));
        memset(bic.tr,0,sizeof(bic.tr));
        memset(pos,0,sizeof(pos));
        n=read();ans=0;res=0;
        fo(i,1,n){
            a[i]=read();
            mn[i]=min(mn[i-1],a[i]);
            if(mn[i-1]==a[i])las[i]=ps[i-1],ps[i]=i;
            if(mn[i-1]>a[i])las[i]=0,ps[i]=i;
            if(mn[i-1]<a[i])ps[i]=ps[i-1];
        }
        xds.build(1,1,n);
        // cerr<<"ZZ"<<endl;
        fo(i,1,n){
            // cerr<<i<<" "<<ps[i]<<" "<<las[ps[i]]<<endl;
            if(mn[i]==mn[i-1])pos[i]=xds.query(1,1,n,max(i,pos[i-1])+1,mn[i]);
            else pos[i]=xds.query(1,1,n,i+1,mn[i]);
            if(pos[i]<=n)bic.ins(pos[i],1);
            // cerr<<pos[i]<<endl;
        }
        // cerr<<endl;
        // cerr<<"ZZ"<<endl;
        fo(i,1,n){
            ans+=bit.qry(1,a[i]-1);
            printf("%lld ",ans+bic.query(i));
            if(!vis[a[i]])bit.ins(a[i],1);
            vis[a[i]]=true;
        }
        printf("\n");
    }
    return 0;
}

T3 小 W 与骑士

所以这个题好像挺简单的???

首先平行的情况,我们直接建边缩点,当然我没有这么写(因为数据水

不平行就直接解方程,然后容斥,设\(f_i\)表示走到的第一个障碍点是i的方案数,因为走路是无环的

所以减去走过来的方案数,一路dfs就行了

AC_code
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
int read(){
    int s=0,t=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')t=-1;ch=getchar();}
    while(isdigit(ch)){s=(s<<1)+(s<<3)+(ch^48);ch=getchar();}
    return s*t;
}
const int N=505;
const int mod=1e9+7;
int ksm(int x,int y){
    int ret=1;
    while(y){
        if(y&1)ret=ret*x%mod;
        x=x*x%mod;y>>=1;
    }return ret;
}
int T,n,x,y,ax,ay,bx,by;
struct node{
    int x,y;
    bool operator < (node a)const{
        if(x!=a.x)return x<a.x;
        return y<a.y;
    }
    bool operator != (node a)const{
        return x!=a.x||y!=a.y;
    }
}no[N];
bool isn[N];
int dp[N*2];
void spj1(){
    if(x*ay!=y*ax)return printf("0\n"),void();
    if(ax*bx<0)return printf("-1\n"),void();
    if(ax<0)return printf("0\n"),void();
    memset(isn,false,sizeof(isn));
    fo(i,1,n)if(no[i].x>=0&&no[i].x*y==no[i].y*x){
        isn[no[i].x]=true;
    }dp[0]=1;
    if(ax){
        fo(i,1,x){
            dp[i]=0;if(isn[i])continue;
            if(i>=ax)dp[i]=(dp[i]+dp[i-ax])%mod;
            if(i>=bx&&ax!=bx)dp[i]=(dp[i]+dp[i-bx])%mod;
        }
        printf("%lld\n",dp[x]);return ;
    }
    if(ay){
        fo(i,1,y){
            dp[i]=0;if(isn[i])continue;
            if(i>=ay)dp[i]=(dp[i]+dp[i-ay])%mod;
            if(i>=by&&ay!=by)dp[i]=(dp[i]+dp[i-by])%mod;
        }
        printf("%lld\n",dp[y]);return ;
    }
}
int jc[N*N*10],inv[N*N*10];
int C(int a,int b){return jc[a]*inv[b]%mod*inv[a-b]%mod;}
int wok(int x,int y){
    int k,b;
    if((bx*ay-by*ax)==0)return 0;
    b=(x*ay-y*ax)/(bx*ay-by*ax);
    if(b*(bx*ay-by*ax)!=(x*ay-y*ax))return 0;
    if(b<0)return 0;
    if(ax){
        k=(x-b*bx)/ax;
        if(k*ax!=x-b*bx)return 0;
        if(k<0)return 0;
    }
    else {
        k=(y-b*by)/ay;
        if(k*ay!=y-b*by)return 0;
        if(k<0)return 0;
    }
    return C(k+b,b);
}
int dfs(int a){
    if(~dp[a])return dp[a];
    int ret=wok(no[a].x,no[a].y);
    if(!ret)return dp[a]=0;
    fo(i,1,n)if(i!=a&&no[i]!=no[i-1]){
        int sm=wok(no[a].x-no[i].x,no[a].y-no[i].y);
        if(!sm)continue;
        ret=(ret-sm*dfs(i)%mod+mod)%mod;
    }
    return dp[a]=ret;
}
void spj2(){
    memset(dp,-1,sizeof(dp));
    no[0].x=x;no[0].y=y;
    printf("%lld\n",dfs(0));
}
signed main(){
    freopen("knight.in","r",stdin);
    freopen("knight.out","w",stdout);
    T=read();
    jc[0]=1;fo(i,1,2500000)jc[i]=jc[i-1]*i%mod;
    inv[0]=1;inv[2500000]=ksm(jc[2500000],mod-2);
    fu(i,2499999,1)inv[i]=inv[i+1]*(i+1)%mod;
    while(T--){
        x=read();y=read();n=read();
        ax=read();ay=read();bx=read();by=read();
        fo(i,1,n)no[i].x=read(),no[i].y=read();
        sort(no+1,no+n+1);
        if(x<0){
            ax=-ax;bx=-bx;x=-x;
            fo(i,1,n)no[i].x=-no[i].x;
        }
        if(y<0){
            ay=-ay;by=-by;y=-y;
            fo(i,1,n)no[i].y=-no[i].y;
        }
        if(ax*by==bx*ay||(!ax&&!ay)||(!bx&&!by))spj1();
        else spj2();
    }
    return 0;
}
posted @ 2022-03-24 21:00  fengwu2005  阅读(101)  评论(0编辑  收藏  举报