计蒜之道复赛 B D F

Posted 可是我不配

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了计蒜之道复赛 B D F相关的知识,希望对你有一定的参考价值。

B题是一个简单的模拟

求一下两个点中间在上deta的整数点

然后更新一下每个点的最后一次经过就好了

 

 1 #include<bits/stdc++.h>
 2 #define cl(a,b) memset(a,b,sizeof(a))
 3 #define debug(x) cerr<<#x<<"=="<<(x)<<endl
 4 using namespace std;
 5 
 6 const int maxn=300+10;
 7 
 8 int gcd(int a,int b){return a?gcd(b%a,a):b;}
 9 int abs(int a){if(a>0)return a;return -a;}
10 
11 int a[maxn][maxn];
12 
13 int main()
14 {
15     int n,m;
16     scanf("%d%d",&n,&m);
17     cl(a,0);
18     for(int i=1;i<=n;i++)
19     {
20         int x1,y1,x2,y2,dx,dy;
21         scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
22         dx=x2-x1;
23         dy=y2-y1;
24         int k=gcd(abs(dx),abs(dy));
25         dx/=k,dy/=k;
26         x2+=dx;
27         while(x1!=x2)
28         {
29 //            debug(x1),debug(y1);
30             a[x1][y1]=i;
31             x1+=dx,y1+=dy;
32         }
33     }
34     int q;
35     scanf("%d",&q);
36     while(q--)
37     {
38         int x,y;
39         scanf("%d%d",&x,&y);
40         printf("%d\n",a[x][y]);
41     }
42     return 0;
43 }/*
44 
45 5 8
46 2 5 5 2
47 5 2 3 8
48 8 4 1 4
49 2 2 5 8
50 8 7 4 1
51 4
52 3 4
53 5 2
54 6 4
55 3 5
56 
57 */

 

D是一个最短路

需要注意的是每个城市群需要加两个点u‘和u‘‘

每个群内的城市连自己的城市群是

u‘->v

v->u‘‘

然后每个城市群之间

u‘->v‘‘

v‘->u‘‘

直接跑一遍spfa就行

需要注意的是:

1.n和m没有规定谁大谁小 所以加点的时候n*2+i和n+i是会冲突的

2.因为最大的值是2e5*2e6>2^31-1 所以ans要用ll存

3.由于上一点的存在 inf也要改……

 

  1 #include<bits/stdc++.h>
  2 #define cl(a,b) memset(a,b,sizeof(a))
  3 #define debug(x) cerr<<#x<<"=="<<(x)<<endl
  4 using namespace std;
  5 typedef long long ll;
  6 
  7 const int MAXN=4e5+10;
  8 const ll INF=2e12;
  9 
 10 struct Edge
 11 {
 12     int v;
 13     int cost;
 14     Edge(int _v=0,int _cost=0):v(_v),cost(_cost) {}
 15 };
 16 
 17 vector<Edge>E[MAXN];
 18 
 19 void addedge(int u,int v,int w)
 20 {
 21     E[u].push_back(Edge(v,w));
 22 }
 23 
 24 bool vis[MAXN];
 25 int cnt[MAXN];
 26 ll dist[MAXN];
 27 int n,m;
 28 int start,over;
 29 
 30 ll SPFA(int start,int n)
 31 {
 32     for(int i=0;i<n+m*2+10;i++)
 33     {
 34         dist[i]=INF;
 35         vis[i]=false;
 36     }
 37     vis[start]=true;
 38     dist[start]=0;
 39     queue<int>que;
 40     while(!que.empty())que.pop();
 41     que.push(start);
 42     memset(cnt,0,sizeof(cnt));
 43     cnt[start]=1;
 44     while(!que.empty())
 45     {
 46         int u=que.front();
 47         que.pop();
 48         vis[u]=false;
 49         for(int i=0; i<E[u].size(); i++)
 50         {
 51             int v=E[u][i].v;
 52             if(dist[v]>dist[u]+E[u][i].cost)
 53             {
 54                 dist[v]=dist[u]+E[u][i].cost;
 55                 if(!vis[v])
 56                 {
 57                     vis[v]=true;
 58                     que.push(v);
 59                     if(++cnt[v]>n) return -1;
 60                 }
 61             }
 62         }
 63     }
 64     return dist[over];
 65 }
 66 
 67 int main()
 68 {
 69     scanf("%d%d",&n,&m);
 70     for(int i=1;i<=m;i++)
 71     {
 72         int k;
 73         scanf("%d",&k);
 74         for(int j=0;j<k;j++)
 75         {
 76             int x;
 77             scanf("%d",&x);
 78             addedge(x,n+m+i,0);
 79             addedge(n+i,x,0);
 80         }
 81     }
 82     int m1;
 83     scanf("%d",&m1);
 84     for(int i=0;i<m1;i++)
 85     {
 86         int u,v,w;
 87         scanf("%d%d%d",&u,&v,&w);
 88         addedge(u,v,w);
 89         addedge(v,u,w);
 90     }
 91     int m2;
 92     scanf("%d",&m2);
 93     for(int i=0;i<m2;i++)
 94     {
 95         int u,v,w;
 96         scanf("%d%d%d",&u,&v,&w);
 97         addedge(n+m+u,n+v,w);
 98         addedge(n+m+v,n+u,w);
 99     }
100     scanf("%d%d",&start,&over);
101     ll ans=SPFA(start,n);
102     printf("%lld\n",ans>=INF?-1:ans);
103     return 0;
104 }/*
105 
106 5 4
107 2 5 1
108 2 2 4
109 1 3
110 2 3 4
111 2
112 1 2 9
113 1 5 18
114 2
115 1 2 6
116 1 3 10
117 1 5
118 
119 */

 

F是一个状压dp

(虽然没有16这么性感的数字 但是18也很明显了~

第一维表示当前状态 01表示是否删除

第二维表示已经删除的步数

用l r来枚举区间

数据范围不是很大(2^n)*n*n是可以容忍的

(也是调了好久啊……

 

 1 #include<bits/stdc++.h>
 2 #define cl(a,b) memset(a,b,sizeof(a))
 3 #define debug(x) cerr<<#x<<"=="<<(x)<<endl
 4 using namespace std;
 5 typedef long long ll;
 6 
 7 const int maxn=20;
 8 const int mod=1000000007;
 9 
10 int gcd(int a,int b)
11 {
12     return a?gcd(b%a,a):b;
13 }
14 
15 bool check(int x,int y)
16 {
17     return x&(1<<y);
18 }
19 
20 int n,k;
21 int a[maxn];
22 int dp[(1<<maxn)][maxn];
23 
24 void solve()
25 {
26     for(int i=0; i<(1<<n); i++)
27     {
28         for(int l=0; l<n; l++)
29         {
30             int tmp=i;
31             if(check(i,l))
32             {
33                 int tmp1=a[l];
34                 for(int r=l; r<n; r++)
35                 {
36                     if(check(i,r))
37                     {
38                         tmp^=(1<<r);
39                         tmp1=gcd(tmp1,a[r]);
40                         if(tmp1<k) break;
41                         for(int j=1; j<=n; j++)
42                         {
43                             dp[i][j]=(dp[i][j]+dp[tmp][j-1])%mod;
44                         }
45                     }
46                 }
47             }
48         }
49     }
50 }
51 
52 int main()
53 {
54     scanf("%d%d",&n,&k);
55     cl(a,0),cl(dp,0);
56     for(int i=0; i<n; i++)
57     {
58         scanf("%d",&a[i]);
59     }
60     dp[0][0]=1;
61     solve();
62     ll ans=0;
63     for(int i=1; i<=n; i++)
64     {
65         ans+=1ll*i*dp[(1<<n)-1][i];
66         ans%=mod;
67     }
68     printf("%lld\n",ans);
69     return 0;
70 }/*
71 
72 4 1
73 1 1 1 1
74 
75 */

 

以上是关于计蒜之道复赛 B D F的主要内容,如果未能解决你的问题,请参考以下文章

2018计蒜之道复赛

2018 计蒜之道 复赛

2016计蒜之道复赛A 百度地图的实时路况

2017计蒜之道复赛 百度地图导航

2016计蒜之道复赛 百度地图的实时路况 floyd+cdq分治

2017 计蒜之道 复赛 Windows画图+百度地图导航