NOIP提高組模擬賽加2
阿新 • • 發佈:2022-06-01
又雙叒叕考炸了。。。
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; }