洛谷 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;
}
posted @ 2021-08-20 21:54  ccz9729  阅读(135)  评论(0编辑  收藏  举报