NOIP提高组模拟赛加2

又双叒叕考炸了。。。

A. 光

我好像也被叫做光来着

这题,怎么说呢,不能说恶心,只能说非常恶心。

他是个大模拟!!!!

心态都打炸了,最后取得了\(0\)分好成绩

代码能力差,而且读题有问题,没有特别注意方向。。

这题思路比较简单,情况有点多,大力讨论吧。

码量还好,也就\(57\)(\(loj\)标准格式\(209\)行,不要问我为什么这么丧心病狂)

code
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=1000005;
int n,m,k,sc[maxn],sh[maxn],sx[maxn],sy[maxn];
struct node{int x,y,idc,idh,idx,idy;}d[maxn];
bool vis[maxn][4];
long long ans=1;
char cc[5];
bool cmp_c(int x,int y){return d[x].x-d[x].y!=d[y].x-d[y].y?d[x].x-d[x].y<d[y].x-d[y].y:d[x].x<d[y].x;}
bool cmp_h(int x,int y){return d[x].x+d[x].y!=d[y].x+d[y].y?d[x].x+d[x].y<d[y].x+d[y].y:d[x].x<d[y].x;}
bool cmp_x(int x,int y){return d[x].x!=d[y].x?d[x].x<d[y].x:d[x].y<d[y].y;}
bool cmp_y(int x,int y){return d[x].y!=d[y].y?d[x].y<d[y].y:d[x].x<d[y].x;}
int get_dir(int &x,int dir){
    bool f1=0,f2=0,f3=0,f4=0;
    int up=sx[d[x].idx+1],down=sx[d[x].idx-1],left=sy[d[x].idy-1],right=sy[d[x].idy+1];
    if(d[up].y==d[x].y+1&&d[up].x==d[x].x&&up!=k)f1=1;
    if(d[right].x==d[x].x+1&&d[right].y==d[x].y&&right!=k)f2=1;
    if(d[down].y==d[x].y-1&&d[down].x==d[x].x&&down!=k)f3=1;
    if(d[left].x==d[x].x-1&&d[left].y==d[x].y&&left!=k)f4=1;
    if(dir==0){if(f1==f4)return 2;if(f1){x=up;return 3;}if(f4){x=left;return 1;}}
    if(dir==1){if(f3==f4)return 3;if(f3){x=down;return 2;}if(f4){x=left;return 0;}}
    if(dir==2){if(f2==f3)return 0;if(f2){x=right;return 3;}if(f3){x=down;return 1;}}
    if(dir==3){if(f1==f2)return 1;if(f1){x=up;return 0;}if(f2){x=right;return 2;}}
}
int re(int dir){if(dir==0)return 2;if(dir==2)return 0;if(dir==1)return 3;if(dir==3)return 1;}
void shot(int ,int);
void work(int now,int dir){
    if(now!=k)dir=get_dir(now,dir);
    if(vis[now][dir])return;
    vis[now][dir]=1;
    shot(now,dir);
}
void shot(int now,int dir){
    if(dir==0){int v=sh[d[now].idh+1];if(vis[v][re(dir)]==0)ans+=d[v].x-d[now].x-1;work(v,dir);}
    if(dir==1){int v=sc[d[now].idc+1];if(vis[v][re(dir)]==0)ans+=d[v].x-d[now].x-1;work(v,dir);}
    if(dir==2){int v=sh[d[now].idh-1];if(vis[v][re(dir)]==0)ans+=d[now].x-d[v].x-1;work(v,dir);}
    if(dir==3){int v=sc[d[now].idc-1];if(vis[v][re(dir)]==0)ans+=d[now].x-d[v].x-1;work(v,dir);}
}
void add(int x,int y){++k;d[k].x=x;d[k].y=y;}
signed main(){
    scanf("%d%d%d",&n,&m,&k);for(int i=1;i<=k;++i)scanf("%d%d",&d[i].x,&d[i].y);
    for(int i=0;i<=m+1;++i)add(0,i),add(n+1,i);
    for(int i=1;i<=n;++i)add(i,0),add(i,m+1);
    ++k;scanf("%d%d",&d[k].x,&d[k].y);
    for(int i=1;i<=k;++i)sc[i]=sh[i]=sx[i]=sy[i]=i;
    sort(sc+1,sc+k+1,cmp_c);sort(sh+1,sh+k+1,cmp_h);sort(sx+1,sx+k+1,cmp_x);sort(sy+1,sy+k+1,cmp_y);
    for(int i=1;i<=k;++i)d[sc[i]].idc=d[sh[i]].idh=d[sx[i]].idx=d[sy[i]].idy=i;
    scanf("%s",cc);
    if(cc[0]=='N'&&cc[1]=='E')work(k,2);
    if(cc[0]=='S'&&cc[1]=='E')work(k,1);
    if(cc[0]=='S'&&cc[1]=='W')work(k,0);
    if(cc[0]=='N'&&cc[1]=='W')work(k,3);
    printf("%lld\n",ans);
    return 0;
}

B. visit

水题,本来以为是\(exlucas\),其实只是\(lucas\)

\(T1\)时间用的有点多,不过还是比较明智的弃掉了。

但是!!但是!!!数组两维空间开反了!!没有开\(long long\)

\(100->60\)........

可恶。然而。

关于答案的求法,我觉得非常显然(不考虑优化的最简狮子)

所以这里不再赘述

code
#include<cstdio>
#include<cstring>
#include<algorithm>

using namespace std;
#define int long long
typedef long long ll;
const int maxn=100005;
int T,mod,n,m;
int p[105],cnt;
int fac[105][maxn],inv[105][maxn];
ll ans;

int qpow(ll x,int y){
    ll ans=1;
    for(;y;y>>=1,x=x*x%mod)if(y&1)ans=ans*x%mod;
    return ans%mod;
}

void pre(){
    int x=mod;
    for(int i=2;i*i<=x;++i)
    if(x%i==0){p[++cnt]=i;x/=i;}
    if(x!=1)p[++cnt]=x;
    for(int k=1;k<=cnt;++k){
        fac[k][0]=1;
        int up=min(p[k],maxn);
        for(int i=1;i<up;++i)fac[k][i]=fac[k][i-1]*1ll*i%p[k];
        inv[k][up-1]=qpow(fac[k][up-1],p[k]-2);
        inv[k][0]=1;
        for(int i=up-2;i;--i)inv[k][i]=inv[k][i+1]*1ll*(i+1)%p[k];
    }
}

int C(int x,int y,int p,int i){
    return fac[i][x]*1ll*inv[i][x-y]%p*inv[i][y]%p;
}
int lucas(int x,int y,int p,int i){
    if(y>x)return 0;
    if(x==y||x==0||x==1)return 1;
    if(x<p&&y<p)return C(x,y,p,i);
    return 1ll*lucas(x%p,y%p,p,i)*lucas(x/p,y/p,p,i)%p;
}
ll exgcd(ll a,ll b,ll &x,ll &y){
	if(b==0){
		x=1;y=0;
		return a;
	}
	ll gcd=exgcd(b,a%b,y,x);
	y-=a/b*x;
	return gcd;
}

ll INV(ll a,ll b){
	ll x,y;
	ll gcd=exgcd(a,b,x,y);
	return (x%b+b)%b;
}
int get_C(int x,int y){
    ll ans=0;
    for(int i=1;i<=cnt;++i){
        ans=ans+lucas(x,y,p[i],i)*1ll*(mod/p[i])*INV(mod/p[i],p[i])%mod;
    } 
    return ans%mod;
}

signed main(){
    scanf("%lld%lld%lld%lld",&T,&mod,&n,&m);
    n=abs(n);m=abs(m);pre();
    int res=T-n-m;
    if(res&1)printf("0\n");
    else{
        int ls=res/2;
        for(int i=0;i<=ls;++i){
            ans=(ans+get_C(T,n+i*2)*1ll*get_C(n+i*2,i)%mod*get_C(m+(ls-i)*2,ls-i)%mod)%mod;
        }
        printf("%lld\n",ans);
    }
    return 0;
}
posted @ 2022-06-01 18:01  Chen_jr  阅读(43)  评论(0编辑  收藏  举报