牛客多校第一場

牛客多校第一場

A. Equivalent Prefixes

題意:兩個序列相等的條件是RMQ(u,l,r) = RMQ(u,l,r),(1lrm1\leq l \leq r\leq m) ,RMQ(u,l,r)代表序列u,的任意區間(l,r)的最小值的序號,求一個最大的P,使得{a1,a2,...ap}\lbrace a_1, a_2,...a_p \rbrace{b1,b2,...bp}\lbrace b_1,b_2,...b_p \rbrace相等

思路:

我們假設lasta[i]=max{jj<i&&aj<ai}last_a[i]= max\lbrace j|j<i \&\& a_j<a_i\rbrace ,也就是aia_i左邊序號最大的小於aia_i的數字的位置,

我們用單調棧去求這個last,求得以後

那麼我們求序列[1,r]的RMQ,就是找到last[r],last[last[r]],last[last[last[r]],的值

如果兩個序列的last數組相同,那麼就證明RMQ(a,l,r)=RMQ(b,l,r)RMQ(a,l,r)=RMQ(b,l,r)

AC代碼:

#include<bits/stdc++.h>
using namespace std;

#define ll long long
const int maxn = 1e5 + 7;
const int inf = 0x3f3f3f3f;
const int mod = 1e9 + 7;
typedef pair<int, int> pis;

int a[maxn], b[maxn];
int lasta[maxn], lastb[maxn];

stack<pis> sta;

int main() { 
    int n;
    while(~scanf("%d", &n)) {
        for (int i = 1; i <= n; i ++) scanf("%d", &a[i]);
        for (int i = 1; i <= n; i ++) scanf("%d", &b[i]);
        while(!sta.empty()) sta.pop();
        sta.push(pis{0, 0});
        for (int i = 1; i <= n; i ++) {
            while(sta.top().first > a[i]) sta.pop();
            lasta[i] = sta.top().second;
            sta.push((pis{a[i], i})); 
        }
        while(!sta.empty()) sta.pop();
        sta.push(pis{0, 0});
        for (int i = 1; i <= n; i ++) {
            while(sta.top().first > b[i]) sta.pop();
            lastb[i] = sta.top().second;
            sta.push((pis{b[i], i})); 
        }
        int cnt = 0;
        for (int i = 1; i <= n; i ++) {
            if(lasta[i] == lastb[i]) cnt ++;
            else break;
        }
        cout << cnt << endl;
    }
    return 0;
}

B.Integration

題意:

已知011+x2dx=π2\int_0^{\infty}\frac{1}{1+x^2}dx=\frac{\pi}{2}

求:1π01i=1n(ai2+x2)dx\frac{1}{\pi}\int_0^{\infty}\frac{1}{\prod\limits_{i=1}^{n}(a_i^2+x^2)}dx

思路:

我們先算1i=1n(ai2+x2)\frac{1}{\prod\limits_{i=1}^{n}(a_i^2+x^2)}
=1a12+x21a22+x21i=3nai2+x2=1(a22a12)(1a12+x21a22+x2)1i=3nai2+x2=1(a22a12)(1a12+x21a22+x2)1a32+x21i=4nai2+x2=1(a22a12)(1a12+x21a32+x21a22+x21a32+x2)1i=4nai2+x2=1(a22a12)(1(a12a32)(1a32+x21a12+x2)1(a32a22)(1a22+x21a32+x2))1i=4nai2+x2=(1a22a121a32a12)1a12+x2+(1a12a221a32a22)1a22+x2+(1a12a321a22a32)1a32+x2=...=i=1n1j=1,j!=in(aj2ai2)1ai2+x2=\frac{1}{a_1^2+x^2} \frac{1}{a_2^2+x^2}\frac{1}{\prod\limits_{i=3}^{n}a_i^2+x^2}\\ =\frac{1}{(a_2^2-a_1^2)}(\frac{1}{a_1^2+x^2}-\frac{1}{a_2^2+x^2})\frac{1}{\prod\limits_{i=3}^{n}a_i^2+x^2}\\ =\frac{1}{(a_2^2-a_1^2)}(\frac{1}{a_1^2+x^2}-\frac{1}{a_2^2+x^2})\frac{1}{a_3^2+x^2}\frac{1}{\prod\limits_{i=4}^{n}a_i^2+x^2}\\ =\frac{1}{(a_2^2-a_1^2)}(\frac{1}{a_1^2+x^2}\frac{1}{a_3^2+x^2}-\frac{1}{a_2^2+x^2}\frac{1}{a_3^2+x^2})\frac{1}{\prod\limits_{i=4}^{n}a_i^2+x^2}\\ =\frac{1}{(a_2^2-a_1^2)}(\frac{1}{(a_1^2-a_3^2)}(\frac{1}{a_3^2+x^2}-\frac{1}{a_1^2+x^2})-\frac{1}{(a_3^2-a_2^2)}(\frac{1}{a_2^2+x^2}-\frac{1}{a_3^2+x^2}))\frac{1}{\prod\limits_{i=4}^{n}a_i^2+x^2}\\ =(\frac{1}{a_2^2-a_1^2}\frac{1}{a_3^2-a_1^2})\frac{1}{a_1^2+x^2}+(\frac{1}{a_1^2-a_2^2}\frac{1}{a_3^2-a_2^2})\frac{1}{a_2^2+x^2}+(\frac{1}{a_1^2-a_3^2}\frac{1}{a_2^2-a_3^2})\frac{1}{a_3^2+x^2}\\ =...\\ =\sum\limits_{i=1}^{n}\frac{1}{\prod\limits_{j=1,j!=i}^{n}(a_j^2-a_i^2)}\frac{1}{a_i^2+x^2}
我們設ci=j=1,j!=in(aj2ai2)c_i=\prod\limits_{j=1,j!=i}^{n}(a_j^2-a_i^2)
=i=1n1ci1ai2+x2原式=\sum\limits_{i=1}^{n}\frac{1}{c_i}\frac{1}{a_i^2+x^2}
那麼
1π01i=1n(ai2+x2)dx=1π0i=1n1ci1ai2+x2=1πi=1n1ci01ai2+x2=1πi=1n1ciπ2ai=i=1n12ciai\frac{1}{\pi}\int_0^{\infty}\frac{1}{\prod\limits_{i=1}^{n}(a_i^2+x^2)}dx\\ =\frac{1}{\pi}\int_0^{\infty}\sum\limits_{i=1}^{n}\frac{1}{c_i}\frac{1}{a_i^2+x^2}\\ =\frac{1}{\pi}\sum\limits_{i=1}^{n}\frac{1}{c_i}\int_0^{\infty}\frac{1}{a_i^2+x^2}\\ =\frac{1}{\pi}\sum\limits_{i=1}^{n}\frac{1}{c_i}\frac{\pi}{2a_i}\\ =\sum\limits_{i=1}^{n}\frac{1}{2c_ia_i}

AC代碼:

#include<bits/stdc++.h>
using namespace std;

#define ll long long
const int maxn = 1e5 + 7;
const int inf = 0x3f3f3f3f;
const int mod = 1e9 + 7;
typedef pair<int, int> pis;

ll a[maxn], b[maxn];
int n;

ll ex_gcd(ll a, ll b, ll &x, ll &y) {
    if(!b) {
        x = 1; y = 0;
        return a;
    }
    ll d = ex_gcd(b, a % b, x, y);
    ll t = x;
    x = y; y = t - a / b * y;
    return d;
}

ll getInv(ll a, ll p) {
    ll x, y;
    ex_gcd(a, p, x, y);
    x = ((x % p) + p) % p;
    return x;
}

ll solve(ll x, int idx) {
    ll res = x;
    for (int i = 1; i <= n; i ++) {
        if(i == idx) continue;
        res *= (b[i] - b[idx] + mod) % mod;
        res %= mod;
    }
    return getInv(res, mod);
}

int main() { 
    while(~scanf("%d", &n)) {
        for (int i = 1; i <= n; i ++) {
            scanf("%lld", &a[i]);
            b[i] = a[i] * a[i] % mod;
        }
        ll ans = 0;
        for (int i = 1; i <= n; i ++)
            ans = (ans + solve(a[i], i)) % mod;
        printf("%lld\n", ans * getInv(2, mod) % mod);
    }
    return 0;
}

C:Euclidean Distance

題意:

給你一些點(a1m,a2m,...,anm)(\frac{a_1}{m},\frac{a_2}{m},...,\frac{a_n}{m}),讓你找一些pip_i,使得i=1n(piai)2\sum\limits_{i=1}^{n}(p_i-a_i)^2最小,pip_i滿足i=1npi=1,pi&gt;=0\sum\limits_{i=1}^{n}p_i=1,p_i&gt;=0

思路:

聽說題解是用拉格朗日乘子法,但我也不會,
我看到有別人用的是貪心
因爲所有的aia_i都是除以m的,所以我們把aia_ipip_i都乘以m,那麼我們就變成了用m步使得面積最小(負數的面積不能變小隻能變大)

在這裏插入圖片描述
那麼貪心的做法就是把大的儘量的變小,因爲是排過序的,所以前面的要比後面的大。
每次都試着把前i-1塊變得跟第i塊平齊,如果不能就把前(i-1)塊全部減小ki1\frac{k}{i-1},保持前面的平齊
在這裏插入圖片描述

AC代碼:

#include<bits/stdc++.h>
using namespace std;

#define ll long long
const int maxn = 5e5 + 5;
const int inf = 0x3f3f3f3f;
const int mod = 1e9 + 7;

ll a[maxn];

bool cmp(ll a, ll b) {
    return a > b;
}

ll gcd(ll a, ll b) {
    return !b ? a : gcd(b, a % b);
}

int main() {
    ll n, m;
    while(~scanf("%lld %lld", &n, &m)) {
        for (int i = 1; i <= n; i ++) 
            scanf("%lld", &a[i]);
        sort(a + 1, a + n + 1, cmp);
        ll k = m;
        for (int i = 2; i <= n; i ++) {
            if(k > (a[i-1] - a[i]) * (i-1)) {
                k -= 1ll * (a[i-1] - a[i]) * (i-1);
            }else {
                for (int j = 1; j <= i-1; j ++) 
                    a[j] = 1ll* (i-1) * a[i-1] - k;
                for (int j = i; j <= n; j ++)
                    a[j] = 1ll * a[j] * (i-1);
                m = 1ll * m * (i-1);
                k = 0;
                break;
            }
        }
        if(k) {
            for (int i = 1; i <= n; i ++) 
                a[i] = 1ll * (a[n] * n) - k;
            m = 1ll * m * n;
        }
        ll ans = 0; 
        for (int i = 1; i <= n; i ++) 
            ans = (ans + 1ll * a[i] * a[i]);
        m = 1ll * m * m;
        ll k1 = gcd(ans, m);
        ans /= k1;
        m /= k1;
        if(m == 1) printf("%lld\n", ans);
        else printf("%lld/%lld\n", ans, m);
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章