1. 程式人生 > 其它 >洛谷 8 月月賽 & 「PMOI」Round · 04

洛谷 8 月月賽 & 「PMOI」Round · 04

T1 T166167 「PMOI-4」人贏

題目大意

給一個數列的前兩項分別為\(n\)\(m\)
\(i\geq3\)\(a_i = a_{i-1}*a_{i-2}\)的個位
給定\(n\),\(m\),\(k\), 求以\(n\)\(m\)為前兩項的數列的第\(k\)
(資料範圍 $0 \leq n,m \leq 9 $ \(1 \leq k \leq 1e12\)

思路

通過觀察樣例可以發發現 \(n,m\)很小 \(k\)很大 因此這道題肯定是有規律的
通過打表我們可以發現 這個數列從第三項開始 每 六項 重複一次
因此我們可以通過找到數列的前六項來找到第\(k\)個數字是多少

AC_CODE

#include <bits/stdc++.h>
#define x first    
#define y second    
//#define int long long 
#define endl '\n' 

using namespace std;
 
typedef pair<int, int> PII ;
typedef long long LL;

template < typename T >
inline void read(T &x)
{
    x = 0; bool f = 0; char ch = getchar();
    while(!isdigit(ch)){f ^= !(ch ^ 45);ch=getchar();}
    while(isdigit(ch)) x= (x<<1)+(x<<3)+(ch&15),ch=getchar();
    x = f ? -x : x;
}
const int N = 2e5 + 10;
int a[N];
void solve() {
    int n, k;
    read(n), read(k);
    LL ans = 0;
    for(int i = 1; i <= n; i ++ ) {
        read(a[i]);
        ans += a[i];
    }
    sort(a + 1, a + 1 + n);
    int res = n - k;
    if(res >= 2)
        cout << a[(res + 1) / 2] << endl;
    else {
        if(res == 0) cout << 0 << endl;
        else if(res == 1) cout << ans << endl;
    }
}

signed main() 
{
    int T = 1;  scanf("%d",&T);
    while(T -- ) {
        solve();
    }
 
    return 0;
}

T2 「PMOI-4」生成樹

題意

給定一個數組 a[] 我們每次取出這個數列中的一個數字放入新陣列中
當這個數字在新陣列中的下標為i 這個數字原本k時 其他的數字
加上\(-1^{i+k+1}k\) 求新陣列中所有的數字最大的和

思路

我們需要求所有的數字最大的和,基於貪心的思想,我們要讓每個數字儘可能的大
當某個數字先選的時候 他會對後面的造成影響,因此我們要讓這個影響儘可能的大
可以使後面的數字儘可能的大
由此add受到下標ik的 奇偶性問題 我們做出以下分析

  • 當我們填到第奇數個數字時 我們需要讓它對後面的影響為正
    - i+k+1是奇數 且 k是負數
    - i+k+1是偶數 且 k
    是正數
    - \(|k|\) 儘可能的大(對後面的影響更大
    - 如果上述兩種情況不存在,我們優先去放 0(0對後面無影響
    - 如果以上都不存在,我們只能放對後面造成負影響的數字,因此我們讓它絕對值儘可能小
  • 偶數同上

AC_CODE

#include <bits/stdc++.h>
#define x first    
#define y second    
#define pb push_back
#define mk make_pair
#define debug(x) cout<<#x" ----> "<<x<<endl
#define rep(i, b, s) for(int i = (b); i <= (s); ++i)
#define pre(i, b, s) for(int i = (b); i >= (s); --i)

//#define int long long 
#define endl '\n' 
#define ios ios::sync_with_stdio(false); cin.tie(0), cout.tie(0)
#define all(v) (v).begin(),(v).end()

using namespace std;
 
typedef unsigned long long ULL;
typedef pair<int, int> PII ;
typedef pair<double, double> PDD ;
typedef long long LL;

const int N = 1e5 + 10;
int n;
PII a[N];
int b[N];
bool cmp(PII p, PII q) {
    return abs(p.x) < abs(q.x);
}
void solve() {
    scanf("%d", &n);
    vector<PII> l, r;
    int cnt = 0;
    for(int i = 0; i < n; i ++ ) {
        int x;
        scanf("%d", &x);
        b[i] = x;
        if(!x) cnt ++;
        else if(x < 0 && x & 1 || x > 0 && !(x & 1)) l.pb({x, i});
        else r.pb({x, i});
    }
    sort(all(l), cmp);
    sort(all(r), cmp);
    int len1 = l.size(), len2 = r.size();
    int t1 = len1 - 1, t2 = len2 - 1, e1 = 0, e2 = 0;
    for(int i = 0; i < n; i ++ ) {
        if((i + 1) & 1) {
            if(t1 >= e1) {
                a[i] = l[t1 --];
            }
            else if(cnt) {
                a[i] = {0, 0};
                cnt --;
            }
            else a[i] = r[e2 ++]; 
        }
        else {
            if(t2 >= e2) a[i] = r[t2 -- ];
            else if(cnt) {
                a[i] = {0, 0};
                cnt --;
            }
            else a[i] = l[e1 ++];
        }
    }
    
    // for(int i = 0; i < n; i ++ ) 
    //     printf("%d %d\n", a[i].x, a[i].y);

    LL res = 0, ans = 0;
    int t = 1;
    for(int i = 0; i < n; i ++, t ^= 1 ) {
        if(a[i].x == 0) {
            ans += res;
            continue;
        }
        ans += (res + a[i].x);
        int p = b[a[i].y];
        if((t + 1 + p) % 2 == 0) res += p;
        else res -= p; 
    }
    printf("%lld", ans);
    
    
}

 
signed main() 
{
    int T = 1; //scanf("%d",&T);
 
    while(T -- ) {
        solve();
    }
 
    return 0;
}