2022 Niuke winter vacation algorithm basic training camp 4

Posted by Eddie Fisher on Sat, 26 Feb 2022 13:00:50 +0100

A.R

thinking

Suppose there is a string containing k k k r strings [L,R], the left and right first P is L,R, then the contribution of this paragraph is ( l − L ) ∗ ( R − r ) (l-L)*(R-r) (l − L) * (R − r), assuming L 1 L_1 L1, in [ L 1 , R ] ( L 1 > L ) [L_1,R](L_1>L) [L1, R](L1 > L) also has strings that meet the conditions. If we still follow the previous calculation method, duplicate strings will be generated in the front. Then we can only calculate the impact of one character X on the string ending with it!

Transfer equation:

  • X = ′ P ′ , d p [ i ] = 0 X='P',dp[i]=0 X=′P′,dp[i]=0
  • X = ′ R ′ & & N u m R = = k , d p [ i ] = P [ i ] − R [ i ] X='R'\&\& Num_R==k ,dp[i]=P[i] - R[i] X=′R′&&NumR​==k,dp[i]=P[i]−R[i]
  • X = o t h e r , d p [ i ] = d p [ i − 1 ] X=other,dp[i]=dp[i-1] X=other,dp[i]=dp[i−1]

code

#include<bits/stdc++.h>
using  namespace std;
#define ll long long
const int maxn = 2e6 + 10;
char ch[maxn];
ll dp[maxn];
vector<int> R;
int main(){
    int n, k; cin >> n >> k;
    int lp = 0, lr = 0, sk = 0;
    for(int i = 1; i <= n; i++){
        cin >> ch[i];
        if(ch[i] == 'R')
            R.push_back(i);
    }
    ll res = 0;
    for(int i = 1; i <= n; i++){
        if(ch[i] == 'P') lp = i, lr += sk, sk = 0;
        else if(ch[i] == 'R'){
            sk++;
            if(sk == k){
                dp[i] = R[lr++] - lp;
                sk--;
            }
            else dp[i] = dp[i - 1];
        }
        else dp[i] = dp[i - 1];
        res += dp[i];
    }
    cout << res;
}

D. Snow halo

thinking

Simplification is to find the shortest distance from a point to a line segment.

Generally speaking, there are two situations

  • The vertical point is on the line segment: the answer is the height of the triangle
  • The vertical point is not on the line segment: the answer is the shorter of the two beveled edges

Knowledge points: Helen formula

p = a + b + c 2 , s = p ∗ ( p − a ) ∗ ( p − b ) ∗ ( p − c ) p=\frac{a+b+c}{2},s=\sqrt{p*(p-a)*(p-b)*(p-c)} p=2a+b+c​,s=p∗(p−a)∗(p−b)∗(p−c) ​

code

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll maxn = 2e5 + 10;
const double eps = 1e-8;
double min(double x, double y) { if (x - y > eps) x = y; return x; }
struct Dir {
	double x, y;
}dir[maxn], s, t;
int main() {
	int n; cin >> n;
	cin >> s.x >> s.y >> t.x >> t.y;
	for (int i = 1; i <= n; i++) cin >> dir[i].x >> dir[i].y;
	double res = 9999999999;
	for (int i = 0; i <= n; i++) {
		double x = s.x + dir[i].x, y = s.y + dir[i].y;
		double a = (s.x - x) * (s.x - x) + (s.y - y) * (s.y - y);
		double b = (s.x - t.x) * (s.x - t.x) + (s.y - t.y) * (s.y - t.y);
		double c = (t.x - x) * (t.x - x) + (t.y - y) * (t.y - y);
		if (b >= a + c || c >= a + b) {
			res = min(res, min(sqrt(b), sqrt(c)));
		}
		else {
			a = sqrt(a); b = sqrt(b); c = sqrt(c);
			double p = (a + b + c) / 2;
			double s = sqrt(p * (p - a) * (p - b) * (p - c));
			double h = s / a * 2;
			res = min(res, h);
		}
		s.x = x, s.y = y;
	}
	cout << fixed << setprecision(8) << res;
}

J. Least common multiple of interval composite number

thinking

First of all, we should know the essence of the greatest common factor and the least common multiple in the prime factor angle

lcm(a,b)The prime factor power of a and b is max, such as 9 and 30, 9 = 3 3 , 30 = 2 ∗ 3 ∗ 5 9=3^3,30=2*3*5 9 = 33,30 = 2 * 3 * 5, so l c m ( 9 , 30 ) = 2 ∗ 3 3 ∗ 5 lcm(9,30)=2*3^3*5 lcm(9,30)=2∗33∗5
gcd(a,b)The prime factor power of a and b is min, such as 9 and 30, 9 = 3 3 , 30 = 2 ∗ 3 ∗ 5 9=3^3,30=2*3*5 9 = 33,30 = 2 * 3 * 5, so g c d ( 9 , 30 ) = 3 gcd(9,30)=3 gcd(9,30)=3

Knowing these two properties, the problem is obvious. Find the prime factor of all sums, and then take max for the power of each prime.

code

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn = 3e4 + 10;
const ll mod = 1e9 + 7;
bool vis[maxn + 10];
vector<int> prime;
int num[maxn];
void E() {
	for (int i = 2; i <= maxn; i++) {
		if (!vis[i]) prime.push_back(i);
		for (int j = 0; j < (int)prime.size() && i * prime[j] <= maxn; j++) {
			vis[i * prime[j]] = true;
			if (i % prime[j] == 0) break;
		}
	}
}
void solve(int x) {
	for (auto& te : prime) {
		int temp = 0;
		while (x % te == 0 && x) {
			x /= te;
			temp++;
		}
		num[te] = max(num[te], temp);
		if (!te) return;
	}
}
ll qpow(ll a, ll x) {
	ll res = 1;
	while (x) {
		if (x & 1) res = res * a % mod;
		a = a * a % mod;
		x >>= 1;
	}
	return res;
}
int main() {
	E();
	int l, r; cin >> l >> r;
	bool is = false;
	for (int i = l; i <= r; i++) {
		if (!vis[i]) continue;
		else is = true;
		solve(i);
	}
	if (!is) {
		cout << -1;
		return 0;
	}
	ll ans = 1;
	for (auto &te:prime) {
		(ans *= qpow(te, num[te])) %= mod;
	}
	cout << ans;
}

1. The explosion of runes and cards

thinking

01 knapsack variant: knapsack with capacity of K becomes knapsack with multiple of capacity of K

The capacity is k, which is reduced to the range of K by taking a mold, such as: a + b = n k a+b=nk a+b=nk, then a % k + b % k = k a\%k+b\%k=k a%k+b%k=k

Therefore, the transfer equation is:
d p [ i ] [ j ] = m a x ( d p [ i − 1 ] [ j ] , d p [ i − 1 ] [ ( j − a [ i ] % k + k ) % k ] + b [ i ] ) dp[i][j]=max(dp[i-1][j],dp[i-1][(j-a[i]\%k+k)\%k]+b[i]) dp[i][j]=max(dp[i−1][j],dp[i−1][(j−a[i]%k+k)%k]+b[i])
According to the habit, we will press the two-dimensional dp into one-dimensional, but we can't press this question.

Because of the mold taking operation, we may have an impact on the results of the last round, such as us d p [ 10 ] = d p [ 7 ] + b [ 10 ] dp[10]=dp[7]+b[10] dp[10]=dp[7]+b[10], now d p [ 7 ] dp[7] dp[7] is when the 10th item is selected d p [ 7 ] dp[7] dp[7], not when the 9th item is selected d p [ 7 ] dp[7] dp[7], so we must distinguish it by two dimensions i i i and i − 1 i-1 i−1.

code

#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll dp[1010][1010], a[1010], b[1010];
int main() {
    int n, k; cin >> n >> k;
    for (int i = 1; i <= n; i++) {
        cin >> a[i] >> b[i];
        a[i] %= k;
    }
    memset(dp, 128, sizeof dp);
    dp[0][0] = 0;
    for (int i = 1; i <= n; i++) {
        for (int j = 0; j < k; j++) {
            dp[i][j] = max(dp[i - 1][j], dp[i - 1][(j - a[i] + k) % k] + b[i]);
        }
    }
    if (dp[n][0] <= 0) dp[n][0] = -1;
    cout << dp[n][0];
}

Topics: Algorithm Dynamic Programming