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

 

E题

终点拆成两个点, 推出公式即可。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 typedef long long ll;
 5 const ll MOD=1e9+7;
 6 ll F[2048];
 7 
 8 void init(){
 9     F[0]=1;F[1]=1;
10     for(ll i=2;i<=2000;++i)
11         F[i]=F[i-1]*i%MOD;
12     return;
13 }
14 
15 ll qpow(ll a,ll b,ll mod){
16     ll ret=1ll%mod;
17     while(b){
18         if(b&1ll) ret=ret*a%mod;
19         a=a*a%mod;
20         b>>=1;
21     }
22     return ret;
23 }
24 
25 ll ex_gcd(ll a,ll b,ll& x,ll& y){
26     if(a==0&&b==0) return -1;
27     if(b==0){
28         x=1;y=0;return a;
29     }
30     ll d=ex_gcd(b,a%b,y,x);
31     y-=a/b*x;
32     return d;
33 }
34 
35 ll inv( ll a,ll n){
36     return qpow(a,n-2,n);
37 }
38 
39 ll getC(int m,int n){
40     if(n>m) return 0;//2 2
41     return F[m]*inv(F[n],MOD)%MOD*inv(F[m-n],MOD)%MOD;
42 }
43 
44 int main(){
45     init();
46     int N,M;
47     while(~scanf("%d%d",&N,&M)){
48         ll a=getC(M+N-4,N-2);
49         ll b=getC(M+N-4,N-1);
50         ll c=getC(M+N-4,M-1);
51         printf("%lld\n",(a*a%MOD-b*c%MOD+MOD)%MOD);
52     }
53     return 0;
54 }
View Code

 

 

I题

直接dp会TLE,后来想切成M天内的小dp,各段再大DP,优化了一点但还是TLE

正确做法应该用类似 矩阵快速幂 的方法 进行dp

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 typedef long long ll;
 5 
 6 ll mod=1e18;
 7 int N,M;
 8 struct Matrix{
 9     ll dat[101][101];
10     struct Matrix operator * (struct Matrix &b)const {
11         struct Matrix ret;
12         for(int i=1;i<=M;++i)
13             for(int j=1;j<=M;++j)
14                 ret.dat[i][j]=0;
15         for(int i=1;i<=M;++i)
16             for(int j=1;j<=M;++j)
17                 for(int k=1;k<=M;++k){
18                     ret.dat[i][j]=max(ret.dat[i][j],this->dat[i][k]+b.dat[k][j]);
19                 }
20         return ret;
21     }
22 }stt;
23 
24 Matrix qPow(Matrix a,int n){
25     Matrix ret;
26     memset(ret.dat,0,sizeof(ret.dat));
27     while(n){
28         if(n&1) ret=ret*a;
29         a=a*a;
30         n>>=1;
31     }
32     return ret;
33 }
34 
35 int main(){
36     while(~scanf("%d%d",&N,&M)){
37         for(int i=1;i<=M;++i)
38             for(int j=1;j<=M;++j)
39                 stt.dat[i][j]=0;
40         for(int i=1;i<=M;++i)
41             for(int j=1;j<=M;++j){
42                 scanf("%lld",&stt.dat[i][j]);
43             }
44         Matrix fnl=qPow(stt,N-1);
45         ll ans=-1ll; 
46         for(int i=1;i<=M;++i)
47             for(int j=1;j<=M;++j){
48                 ans=max(ans,fnl.dat[i][j]);
49             }
50         printf("%lld\n",ans);
51     }
52     return 0;
53 }
View Code

 

 

To be continued !

posted on 2018-07-25 01:16  Emiya_Kiritsugu  阅读(486)  评论(0编辑  收藏  举报

导航