打到一半已经不想写了,来写博客吧,希望能进队
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 }