题目链接: https://www.jisuanke.com/contest/1408
A题
模拟一个BFS,输出最后一轮(层)被搜索的点中坐标最小的,比较坑的是 K==N*M 需要特判
1 #include <bits/stdc++.h> 2 #define fst first 3 #define scd second 4 #define ingrid(x,y) (x)>=1&&(x)<=N&&(y)>=1&&(y)<=M 5 using namespace std; 6 typedef pair<int ,int > pii; 7 8 bool graph[2001][2001]; 9 queue< pii > Q; 10 int N,M; 11 int dx[4]={0,0,1,-1}; 12 int dy[4]={1,-1,0,0}; 13 14 pii getmin(pii a,pii b){ 15 if(a.fst!=b.fst) return a.fst<b.fst?a:b; 16 return a.scd<=b.scd?a:b; 17 } 18 19 int main(){ 20 while(~scanf("%d%d",&N,&M)){ 21 int K; 22 scanf("%d",&K); 23 pii ans; 24 memset(graph,false,sizeof(graph)); 25 while(!Q.empty()) Q.pop(); 26 for(int i=0;i<K;++i){ 27 pii tmp; 28 scanf("%d%d",&tmp.fst,&tmp.scd); 29 graph[tmp.fst][tmp.scd]=true; 30 Q.push(tmp); 31 ans=tmp; 32 } 33 if(K==N*M) { printf("%d %d\n",ans.fst,ans.scd);continue;} 34 int tot=0; 35 for(;;){ 36 if(tot==N*M) break; 37 pii mm=make_pair(N+1,M+1); 38 int cnt=Q.size(); 39 tot+=cnt; 40 while(cnt--){ 41 pii u=Q.front();Q.pop(); 42 int ux=u.fst,uy=u.scd; 43 for(int i=0;i<4;++i){ 44 int nx=ux+dx[i],ny=uy+dy[i]; 45 if(ingrid(nx,ny)&&graph[nx][ny]==false){ 46 pii tmp=make_pair(nx,ny); 47 graph[nx][ny]=true; 48 Q.push(tmp); 49 mm=getmin(mm,tmp); 50 } 51 } 52 } 53 if(Q.size()+tot==N*M) { 54 ans=mm; 55 break; 56 } 57 } 58 printf("%d %d\n",ans.fst,ans.scd); 59 } 60 return 0; 61 }
B题
元素为(1~N)的序列,问逆序对有K个时,有几种排列。
1
1 1
1 2 2 1
1 3 5 6 5 3 1
... ...
设逆序对个数 num(N,K)表示 长度为N,逆序对个数为K的排列组合个数,有递推式 num(N+1,K)=num(N,K)+num(N+1,K-1)-num(N,K-N-1) ;num(N,0)=1
//luogu有类似题目
此题比较坑的地方是卡内存,必须储存询问,离线用滚动数组计算递推式。间接排序是个好东西。
1 #include <bits/stdc++.h> 2 #define fst first 3 #define scd second 4 using namespace std; 5 6 typedef pair<int ,int > pii; 7 const int MOD=1e9+7; 8 int num[2][5001]; 9 int ans[5001]; 10 pii query[5001]; 11 int _id[5001]; 12 int tmpid; 13 void solve(){ 14 int cntid=1; 15 int cur=0; 16 for(int i=0;i<5000;++i){ 17 memset(num[cur^1],0,sizeof(num[cur^1])); 18 num[cur^1][0]=1; 19 int bound=i*(i+1)/2; 20 for(int j=1;j<=5000&&j<=bound;++j) 21 { 22 if(j-i-1>=0) num[cur^1][j]=((num[cur^1][j-1]+num[cur][j])%MOD-num[cur][j-i-1]+MOD)%MOD; 23 else num[cur^1][j]=(num[cur^1][j-1]+num[cur][j])%MOD; 24 } 25 cur^=1; 26 while(cntid<tmpid&&i+1==query[_id[cntid]].fst) { 27 int KK=query[_id[cntid]].scd; 28 ans[_id[cntid]]=num[cur][KK]; 29 cntid++;// Don't forget ! 30 } 31 } 32 } 33 34 int N,K; 35 36 bool cmp(int i,int j){ 37 pii a=query[i],b=query[j]; 38 if(a.fst!=b.fst)return a.fst<b.fst; 39 return a.scd<b.scd; 40 } 41 42 int main(){ 43 tmpid=1; 44 while(~scanf("%d%d",&N,&K)){ 45 _id[tmpid]=tmpid; 46 query[tmpid]=make_pair(N,K); 47 tmpid++; 48 } 49 sort(_id+1,_id+tmpid,cmp); 50 solve(); 51 for(int i=1;i<tmpid;++i){ 52 printf("%d\n",ans[i]); 53 } 54 return 0; 55 }
D题
了解题意后答案就是一系列组合数的积,可以将这一系列组合数的积,转化公式( ∑Ui)!/∏(Ui!)
1 #include <bits/stdc++.h> 2 using namespace std; 3 #define fst first 4 #define scd second 5 typedef pair<int ,int > pii; 6 typedef long long ll; 7 8 const ll MOD=1e9+7; 9 10 ll F[1000000+6]; 11 ll ans; 12 13 void init(){ 14 F[1]=1;F[2]=2; 15 for(ll i=3;i<=1000000;++i) 16 F[i]=F[i-1]*i%MOD; 17 } 18 19 ll inv(ll a,ll m){ 20 if(a==1) return 1; 21 return inv(m%a,m)*(m-m/a)%m; 22 } 23 24 int tot; 25 int A[1000000+6]; 26 int main(){ 27 init(); 28 int N; 29 while(~scanf("%d",&N)){ 30 tot=0; 31 for(int i=0;i<N;++i) { 32 scanf("%d",&A[i]); 33 tot+=A[i]; 34 } 35 ans=F[tot]; 36 for(int i=0;i<N;++i) { 37 ans=ans*inv(F[A[i]],MOD)%MOD; 38 } 39 printf("%lld\n",ans); 40 } 41 return 0; 42 }
To be continued !