8.1日总结


打到一半已经不想写了,来写博客吧,希望能进队


7.31地址
C题:
题意:给定一个长为n,宽位m的矩形,然后两个人依次往矩形里面画半径为n的圆,问先画的人会赢还是后画的人会赢

解法:类比NIM博弈,你先手一个动作,如果我能通过模仿你的动作让局势再回到最开始的状态,就能让你输。这道题也一样,只要这个圆不大到让后手所画的圆构不成对称图形,那么先手就输了。圆最大的标准就是它不会大的超过最短边的一半

代码有点走样,关键是上边懂了就好

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cmath>
 4 using namespace std;
 5 
 6 int main() {
 7     int T; scanf("%d", &T);
 8     while (T--) {
 9         int a, b, r; 
10         cin >> a >> b >> r;
11         int tmp = 4*r*r;
12         if (tmp<(a*a + b*b) && a*a>tmp && b*b > tmp)
13             cout << "The first one is winner." << endl;
14         else cout << "The second one is winner." << endl;
15     }
16     return 0;
17 }
18 8.1场地址 

A题:
题意:给定一个数,求大于等于它的第一个(2^a*3^b*5^c*7^d)的数
解法:打表,之后二分即可

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<set>
 4 using namespace std;
 5 typedef long long ll;
 6 const int maxn = 1e7 + 5;
 7 ll sum[maxn];
 8 multiset<ll>s;
 9 int tot = 0;
10 
11 ll poww(ll a, ll b) {
12     ll ans = 1, base = a;
13     while (b != 0) {
14         if (b & 1 != 0)ans *= base;
15         base *= base; b >>= 1;
16     }
17     return ans;
18 }
19 
20 //这里的30是试出来的
21 void generate() {
22     for (int i = 0; i < 30; i++) {
23         ll ti = poww(7, i);
24         for (int j = 0; j < 30; j++) {
25             ll tj = poww(5, j);
26             for (int k = 0; k < 30; k++) {
27                 ll tk = poww(3, k);
28                 for (int l = 0; l < 30; l++) {
29                     ll tl = poww(2, l);
30                     ll now = ti*tj*tk*tl;
31                     if (now > 7e9+1)break;
32                     else s.insert(now);
33                 }
34             }
35         }
36     }
37     return;
38 }
39 
40 
41 int main() {
42     int T; scanf("%d", &T);
43     generate();
44     while (T--) {
45         int n; scanf("%d", &n);
46         printf("%lld
", *s.lower_bound(n));
47     }
48     return 0;
49 }

B题:
题意:给出一个数n,我们想求出Σ(1/(k*k)),k属于1~n

解法:打表,由于题目要求精度为小数点后5位,那么当k大于1e6的时候公式的值累加就已经不起作用了,这也是题目为什么不告诉你n的原因

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<string>
 4 #include<iostream>
 5 using namespace std;
 6 const int maxn = 1e6;
 7 string s;
 8 double sum[maxn + 7];
 9 
10 int main() {
11     sum[0] = 0;
12     for (int i = 1; i <= maxn; i++)
13         sum[i] = sum[i - 1] + double(1.0 / (1.0*i *1.0* i));
14     while (cin >> s) {
15         if (s.size() > 6) {printf("%.5lf
", sum[maxn]);continue;}
16         int ans = 0;
17         for (int i = 0; i < s.size(); i++) ans = ans * 10 + s[i] - '0';
18         printf("%.5lf
", double(sum[ans]));
19     }
20     return 0;
21 }

J题:
题意:有n个点,m条边,有一个人要从起点走到终点,他只会走最短路,你要往路上设置路障,让他至少碰到一次路障,每条路上的路障费用等于那条路的权值(路的长度为1),求设置路障的最小花费

解法:首先他只会走最短路,那么我就把所有最短路求出来,注意到所有路的长度都为1,那么只需要跑一遍最短路算法即可确定边的归属,之后我们想象敌人碰到一次路障之后就前进了,那么题目就转换成了至少割掉几条边起点到终点就不连通了,又因为边上有权值,那么这个问题就变成了一个最小割问题,和最大流等效,所以我们直接用Dicnic算法求解即可

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<algorithm>
  4 #include<vector>
  5 #include<queue>
  6 using namespace std;
  7 const int maxn = 1e5 + 5;
  8 const int maxx = 1000 + 5;
  9 const int INF = 0x3f3f3f3f;
 10 int n, m, s, t;
 11 
 12 int g[maxx][maxx], val[maxx][maxx];
 13 int dis[maxx], vis[maxx];
 14 //dijkstra
 15 void init(int n)
 16 {
 17     memset(vis, 0, sizeof(vis));
 18     for (int i = 1; i <= n; i++) {
 19         for (int j = 1; j <= n; j++) {
 20             g[i][j] = INF;
 21         }
 22         dis[i] = INF;
 23     }
 24 }
 25 
 26 void dijkstra(int s, int n)
 27 {
 28     dis[s] = 0;
 29     for (int i = 1; i < n; i++) {
 30         int mn = INF, x;
 31         for (int j = 1; j <= n; j++) {
 32             if (!vis[j] && dis[j] < mn)mn = dis[x = j];
 33         }
 34         vis[x] = 1;
 35         for (int j = 1; j <= n; j++) {
 36             dis[j] = min(dis[j], dis[x] + g[x][j]);
 37         }
 38     }
 39 }
 40 
 41 
 42 //最大流
 43 struct Edge
 44 {
 45     int from, to, cap, flow;
 46     Edge(int u, int v, int c, int f) :from(u), to(v), cap(c), flow(f) {}
 47 };
 48 struct Dinic
 49 {
 50     //  int n,m;
 51     int s, t;
 52     vector<Edge>edges;        //边数的两倍
 53     vector<int> G[maxn];      //邻接表,G[i][j]表示结点i的第j条边在e数组中的序号
 54     bool vis[maxn];           //BFS使用
 55     int d[maxn];              //从起点到i的距离
 56     int cur[maxn];            //当前弧下标
 57     void init()
 58     {
 59         for (int i = 0; i <= n + 1; i++)
 60             G[i].clear();
 61         edges.clear();
 62     }
 63     void AddEdge(int from, int to, int cap)
 64     {
 65         edges.push_back(Edge(from, to, cap, 0));
 66         edges.push_back(Edge(to, from, 0, 0));        //反向弧
 67         int mm = edges.size();
 68         G[from].push_back(mm - 2);
 69         G[to].push_back(mm - 1);
 70     }
 71     bool BFS()
 72     {
 73         memset(vis, 0, sizeof(vis));
 74         queue<int>q;
 75         q.push(s);
 76         d[s] = 0;
 77         vis[s] = 1;
 78         while (!q.empty())
 79         {
 80             int x = q.front(); q.pop();
 81             for (int i = 0; i < G[x].size(); i++)
 82             {
 83                 Edge &e = edges[G[x][i]];
 84                 if (!vis[e.to] && e.cap > e.flow)
 85                 {
 86                     vis[e.to] = 1;
 87                     d[e.to] = d[x] + 1;
 88                     q.push(e.to);
 89                 }
 90             }
 91         }
 92         return vis[t];
 93     }
 94 
 95     int DFS(int x, int a)
 96     {
 97         if (x == t || a == 0)
 98             return a;
 99         int flow = 0, f;
100         for (int &i = cur[x]; i < G[x].size(); i++)
101         {
102             Edge &e = edges[G[x][i]];
103             if (d[x] + 1 == d[e.to] && (f = DFS(e.to, min(a, e.cap - e.flow))) > 0)
104             {
105                 e.flow += f;
106                 edges[G[x][i] ^ 1].flow -= f;
107                 flow += f;
108                 a -= f;
109                 if (a == 0)
110                     break;
111             }
112         }
113         return flow;
114     }
115 
116     int Maxflow(int s, int t)
117     {
118         this->s = s;
119         this->t = t;
120         int flow = 0;
121         while (BFS())
122         {
123             memset(cur, 0, sizeof(cur));
124             flow += DFS(s, INF);
125         }
126         return flow;
127     }
128 }dc;
129 
130 int main() {
131     int T; scanf("%d", &T);
132     while (T--) {
133         scanf("%d%d", &n, &m);
134         init(n);
135         for (int i = 0; i < m; i++) {
136             int u, v, w;
137             scanf("%d%d%d", &u, &v, &w);
138             g[u][v] = g[v][u] = 1;
139             val[u][v] = val[v][u] = w;
140         }
141         dijkstra(1, n);
142         dc.init();
143         for (int i = 1; i <= n; i++)
144             for (int j = 1; j <= n; j++)
145                 if (g[i][j] == 1 && dis[i] + 1 == dis[j]) {
146                     dc.AddEdge(i, j, val[i][j]);
147                 }
148         s = 1, t = n;
149         printf("%d
", dc.Maxflow(s, t));
150     }
151     return 0;
152 }
原文地址:https://www.cnblogs.com/romaLzhih/p/9489794.html