2018徐州邀请赛

题目链接: 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 }
View Code

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 }
View Code

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 }
View Code

To be continued !

猜你喜欢

转载自www.cnblogs.com/Kiritsugu/p/9363613.html