Luke Skywalker got locked up in a rubbish shredder between two presses. R2D2 is already working on his rescue, but Luke needs to stay alive as long as possible. For simplicity we will assume that everything happens on a straight line, the presses are initially at coordinates 0 and L, and they move towards each other with speed v1 and v2, respectively. Luke has width d and is able to choose any position between the presses. Luke dies as soon as the distance between the presses is less than his width. Your task is to determine for how long Luke can stay alive.
The first line of the input contains four integers d, L, v1, v2 (1 ≤ d, L, v1, v2 ≤ 10 000, d < L) — Luke's width, the initial position of the second press and the speed of the first and second presses, respectively.
Print a single real value — the maximum period of time Luke can stay alive for. Your answer will be considered correct if its absolute or relative error does not exceed 10 - 6.
Namely: let's assume that your answer is a, and the answer of the jury is b. The checker program will consider your answer correct, if .
2 6 2 2
1.00000000000000000000
1 9 1 2
2.66666666666666650000
In the first sample Luke should stay exactly in the middle of the segment, that is at coordinates [2;4], as the presses move with the same speed.
In the second sample he needs to occupy the position . In this case both presses move to his edges at the same time.
题意:
在区间[0,L]内选取一个长为d的区间,每秒原区间左端向右移v1,右端向左移v2求使得该区间最长的选址能维持的时间
题解:
二分实数判断即可
#include<iostream> #include<cstdio> #include<cstdlib> #include<algorithm> #include<cstring> #include<cmath> #include<vector> #include<queue> using namespace std; typedef double DB; DB d,L,v1,v2,ans; bool Judge(DB now) { //if (L - v2*now - v1*now <= 0) return false; return d <= (L - v2*now - v1*now); } int main() { #ifdef YZY freopen("yzy.txt","r",stdin); #endif DB l = 0; DB r = 1E5; cin >> d >> L >> v1 >> v2; for (int i = 1; i <= 60; i++) { DB mid = (l+r) / 2; if (Judge(mid)) l = mid; else r = mid; } printf("%.6f",l); return 0; }
You are given an alphabet consisting of n letters, your task is to make a string of the maximum possible length so that the following conditions are satisfied:
The first line of the input contains a single integer n (2 ≤ n ≤ 26) — the number of letters in the alphabet.
The next line contains n integers ai (1 ≤ ai ≤ 109) — i-th of these integers gives the limitation on the number of occurrences of the i-th character in the string.
Print a single integer — the maximum length of the string that meets all the requirements.
3 2 5 5
11
3 1 1 2
3
For convenience let's consider an alphabet consisting of three letters: "a", "b", "c". In the first sample, some of the optimal strings are: "cccaabbccbb", "aabcbcbcbcb". In the second sample some of the optimal strings are: "acc", "cbc".
题意:
给出字母表前n位,每个字母最多使用ai次,且每个字母使用次数必须和其它字母使用次数严格不同,问这样能组成的字符串最长长度是多少
题解:
从大到小判断当前数字是否使用过即可
错误:
MAX在转移的时候没注意数值变化
#include<iostream> #include<cstdio> #include<cstdlib> #include<algorithm> #include<cstring> #include<cmath> #include<vector> #include<queue> using namespace std; typedef long long LL; LL num[30],ans = 0; int n,MAX; int main() { #ifdef YZY freopen("yzy.txt","r",stdin); #endif cin >> n; for (int i = 0; i < n; i++) cin >> num[i]; sort(num,num+n); ans = MAX = num[n-1]; for (int i = n-2; i >= 0; i--) { if (num[i] < MAX) { ans += num[i]; MAX = num[i]; } else { MAX = MAX-1; ans += 1LL*MAX; if (!MAX) break; } } cout << ans; return 0; }
One day student Vasya was sitting on a lecture and mentioned a string s1s2... sn, consisting of letters "a", "b" and "c" that was written on his desk. As the lecture was boring, Vasya decided to complete the picture by composing a graph G with the following properties:
Vasya painted the resulting graph near the string and then erased the string. Next day Vasya's friend Petya came to a lecture and found some graph at his desk. He had heard of Vasya's adventure and now he wants to find out whether it could be the original graph G, painted by Vasya. In order to verify this, Petya needs to know whether there exists a string s, such that if Vasya used this s he would produce the given graph G.
The first line of the input contains two integers n and m — the number of vertices and edges in the graph found by Petya, respectively.
Each of the next m lines contains two integers ui and vi (1 ≤ ui, vi ≤ n, ui ≠ vi) — the edges of the graph G. It is guaranteed, that there are no multiple edges, that is any pair of vertexes appear in this list no more than once.
In the first line print "Yes" (without the quotes), if the string s Petya is interested in really exists and "No" (without the quotes) otherwise.
If the string s exists, then print it on the second line of the output. The length of s must be exactly n, it must consist of only letters "a", "b" and "c" only, and the graph built using this string must coincide with G. If there are multiple possible answers, you may print any of them.
2 1 1 2
Yes aa
4 3 1 2 1 3 1 4
No
In the first sample you are given a graph made of two vertices with an edge between them. So, these vertices can correspond to both the same and adjacent letters. Any of the following strings "aa", "ab", "ba", "bb", "bc", "cb", "cc" meets the graph's conditions.
In the second sample the first vertex is connected to all three other vertices, but these three vertices are not connected with each other. That means that they must correspond to distinct letters that are not adjacent, but that is impossible as there are only two such letters: a and c.
#include<iostream> #include<cstdio> #include<cstdlib> #include<algorithm> #include<cstring> #include<cmath> #include<vector> #include<queue> using namespace std; const int maxn = 510; vector <int> v1[maxn],v2[maxn]; queue <int> q; bool EDG[maxn][maxn]; int du[maxn],mark[maxn],n,m; int main() { #ifdef YZY freopen("yzy.txt","r",stdin); #endif cin >> n >> m; memset(EDG,0,sizeof(EDG)); for (int i = 0; i < m; i++) { int x,y; scanf("%d%d",&x,&y); EDG[x][y] = EDG[y][x] = 1; ++du[x]; ++du[y]; v1[x].push_back(y); v1[y].push_back(x); } for (int i = 1; i <= n; i++) for (int j = 1; j <= n; j++) if (i != j && !EDG[i][j]) v2[i].push_back(j); for (int i = 1; i <= n; i++) if (du[i] == n-1) mark[i] = 2; for (int i = 1; i <= n; i++) if (!mark[i]) { mark[i] = 1; q.push(i); while (!q.empty()) { int k = q.front(); q.pop(); for (int j = 0; j < v1[k].size(); j++) { int to = v1[k][j]; if (mark[to] == 2 || mark[to] == mark[k]) continue; if (mark[to] && mark[to] != mark[k]) { printf("No"); return 0; } mark[to] = mark[k]; q.push(to); } for (int j = 0; j < v2[k].size(); j++) { int to = v2[k][j]; if (mark[to] == 2 || mark[to] == mark[k]) { printf("No"); return 0; } if (mark[to] && mark[to] != mark[k]) continue; mark[to] = (mark[k] == 1)?3:1; q.push(to); } } } printf("Yes\n"); for (int i = 1; i <= n; i++) printf("%c",mark[i]-1+'a'); return 0; }
You are given array ai of length n. You may consecutively apply two operations to this array:
Please note that each of operations may be applied at most once (and may be not applied at all) so you can remove only one segment and each number may be changed (increased or decreased) by at most 1. Also note, that you are not allowed to delete the whole array.
Your goal is to calculate the minimum number of coins that you need to spend in order to make the greatest common divisor of the elements of the resulting array be greater than 1.
The first line of the input contains integers n, a and b (1 ≤ n ≤ 1 000 000, 0 ≤ a, b ≤ 109) — the length of the array, the cost of removing a single element in the first operation and the cost of changing an element, respectively.
The second line contains n integers ai (2 ≤ ai ≤ 109) — elements of the array.
Print a single number — the minimum cost of changes needed to obtain an array, such that the greatest common divisor of all its elements is greater than 1.
3 1 4 4 2 3
1
5 3 2 5 17 13 5 6
8
8 3 4 3 7 5 4 3 12 9 4
13
In the first sample the optimal way is to remove number 3 and pay 1 coin for it.
In the second sample you need to remove a segment [17, 13] and then decrease number 6. The cost of these changes is equal to2·3 + 2 = 8 coins.
题意:
有一个长度为n的数组,可进行两种操作:
1.删去其中一段连续的数字,并付出n*a的代价
2.将其中一个元素+1或-1并付出b的代价
1操作只能进行一次,2操作对每个数都只能进行一次,问最少付出多少代价能使整个数组最大公约数大于1
题解:
由题意,显然至少数组会留下第一个数或最后一个数
那么num[1]、num[1]+-1、num[n]、num[n]+-1这六个数中必有一个存在题解数组里,将他们分解质因数,那么题解数组里至少含有这些质因数的其中一个,设为k,可对每个数判断是否整除k(略)
记f[i]为从左到右进行到i位置,每次只进行2操作或不进行的代价
记g[j]为从右到左进行到j位置,同上
那么答案为f[i]+g[j]+(j-i-1)*a
即(f[i]-i*a) + (g[j]+j*a)-a
对于括号内的数维护最小值,暴力forforfor...
对于质数用Miller_Rubin(好像是这个名?费马小定理+二次判定定理)
#include<iostream> #include<cstdio> #include<cstdlib> #include<algorithm> #include<cstring> #include<cmath> #include<vector> #include<queue> #include<map> using namespace std; typedef long long LL; const int maxn = 1E6 + 10; map <int,bool> M; LL n,a,b,num[maxn],f[maxn],g[maxn],mi[maxn],mi2[maxn],ans = 1E17; bool flag; void cal(LL x) { int R = 0; f[0] = mi[0] = g[n+1] = 0; mi2[n+1] = 1LL*(n+1)*a; for (int i = 1; i <= n; i++) { LL sum; if (num[i] % x == 0) sum = 0; else if ((num[i]+1) % x == 0) sum = b; else if ((num[i]-1) % x == 0 && num[i]-1>0) sum = b; else { R = i; break; } f[i] = f[i-1] + sum; mi[i] = min(f[i]-1LL*a*1LL*i,mi[i-1]); if (i == n) ans = min(ans,f[i]); } if (R) for (int i = R; i <= n; i++) mi[i] = mi[i-1]; LL L = 0; for (int i = n; i; i--) { LL sum; if (num[i] % x == 0 && num[i]) sum = 0; else if ((num[i]+1) % x == 0 && num[i]+1>0) sum = b; else if ((num[i]-1) % x == 0 && num[i]-1>0) sum = b; else { L = i; break; } g[i] = g[i+1]+sum; mi2[i] = min(mi2[i+1],g[i]+1LL*a*1LL*i); if (i == 1) ans = min(ans,g[i]); } if (L) for (int i = L; i; i--) mi2[i] = mi2[i+1]; for (int i = 1; i <= n+1; i++) ans = min(ans,mi[i-1]+mi2[i]-a); } LL ksm(LL a,LL x,LL y) { if (x == 0) return 1; LL r = ksm(a,x/2,y); LL ret = r*r%y; if (ret == 1 && r != 1 && r != y-1) flag = 0; if (x&1) ret = ret*a%y; return ret; } bool M_B(LL x) { for (int i = 1; i <= 10; i++) { flag = true; LL a = rand()%(x-1)+1; LL ret = ksm(a,x-1,x); if (ret != 1 || !flag) return false; } return true; } void solve(LL now) { if (now <= 1) return; if (M_B(now) && !M[now]) cal(now),M[now] = 1; else { LL SQRT = sqrt(now); for (int i = 2; i <= SQRT; i++) if (now % i == 0) { if (M_B(i) && !M[i]) cal(i),M[i] = 1; LL j = now/i; if (M_B(j) && !M[j]) cal(j),M[j] = 1; } } } int main() { #ifdef YZY freopen("yzy.txt","r",stdin); #endif cin >> n >> a >> b; for (int i = 1; i <= n; i++) scanf("%I64d",&num[i]); solve(num[1]); solve(num[1]-1); solve(num[1]+1); solve(num[n]); solve(num[n]-1); solve(num[n]+1); cout << ans; return 0; }