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
受到下標i
和k
的 奇偶性問題 我們做出以下分析
- 當我們填到第奇數個數字時 我們需要讓它對后面的影響為正
-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;
}