A广义肥波
快速幂模板
/*
*@author SunLakeWalk
*/
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <iomanip>
#include <limits.h>
#include <sstream>
#include <vector>
#include <queue>
#include <deque>
#include <stack>
#include <map>
#include <unordered_map>
#include <unordered_set>
#include <set>
//#pragma GCC optimize(2)
//#pragma GCC optimize(3, "Ofast", "inlin")
using namespace std;
#define ios ios::sync_with_stdio(false) , cin.tie(0)
#define x first
#define y second
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> PII;
const int N = 100010, INF = 0x3f3f3f3f, mod = 1e9 + 7, base = 131;
const double eps = 1e-6, PI = acos(-1);
LL a, b, m, n;
LL f[N];
LL qmi(LL a, LL b) {
LL ans = 1;
while (b) {
if (b & 1) ans = ans * a % mod;
a = a * a % mod;
b >>= 1;
}
return ans;
}
void work() {
cin >> a >> b >> m >> n;
f[1] = f[2] = m;
for (LL i = 3; i <= n; i ++ ) {
LL x = qmi(f[i - 1], a) % mod;
LL y = qmi(f[i - 2], b) % mod;
f[i] = x * y % mod;
}
cout << f[n] << endl;
}
int main() {
work();
return 0;
}
小D和他的魔法石
当k=0时,毫无疑问,他是一个完全背包问题
当k!=0时,我们可以通过交换,将价值最大的魔法,和体积最小的石头的魔法交换,我们只选择当前的石头就好了
但是要注意这里的,k一定要交换完,所以,n=2也是一种特殊情况,交换2 * t + 1
和 2 * t
次是不一样的。
/*
*@author SunLakeWalk
*/
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <iomanip>
#include <limits.h>
#include <sstream>
#include <vector>
#include <queue>
#include <deque>
#include <stack>
#include <map>
#include <unordered_map>
#include <unordered_set>
#include <set>
//#pragma GCC optimize(2)
//#pragma GCC optimize(3, "Ofast", "inlin")
using namespace std;
#define ios ios::sync_with_stdio(false) , cin.tie(0)
#define x first
#define y second
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> PII;
const int N = 1010, INF = 0x3f3f3f3f, mod = 1e9 + 7, base = 131;
const double eps = 1e-6, PI = acos(-1);
int n, m, k;
LL a[N], b[N];
LL f[N];
void work() {
cin >> n >> m >> k;
for (int i = 1; i <= n; i ++ ) cin >> a[i];
for (int i = 1; i <= n; i ++ ) cin >> b[i];
if (k == 0 || n == 2) {
if (k % 2) swap(b[1], b[2]);
for (int i = 1; i <= n; i ++ )
for (int j = a[i]; j <= m; j ++ )
f[j] = max(f[j], f[j - a[i]] + b[i]);
cout << f[m] << endl;
return;
}
LL mina = 1e9, maxb = 0;
for (int i = 1; i <= n; i ++ ) {
mina = min(mina, a[i]);
maxb = max(maxb, b[i]);
}
cout << m / mina * maxb << endl;
}
int main() {
work();
return 0;
}
C宝石街
还是不多懂这个题
让总用时不超过t的情况下,在连续区间内的和尽可能的大
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define int long long
const int N = 6e7 + 10;
int n, t, type, p;
int a[N], s[N];
signed main() {
scanf("%lld%lld%lld", &n, &t, &type);
if (type == 1) {
for (int i = 1; i <= n; i ++ ) scanf("%lld", &a[i]);
}
else {
scanf("%lld%lld", &a[1], &p);
for (int i = 2; i <= n; i ++ ) {
int x = a[i - 1] ^ (a[i - 1] << 13);
int y = x ^ (x >> 17);
a[i] = (y ^ (y << 5)) % p + 1;
}
}
/*
如果从第i个位置拿起一个宝石,走到终点x需要消多少时间呢?
需要x-i
那么,我们将时间的当作背包容量,将点i走到终点p所消耗的时间当作物品
体积。
所取得宝石,一定是一段连续得区间,如果他在当前拿了,然后在后面再丢掉
的话,不如一开始就不拿或者少拿。如果他在当前位置拿了,然后走到下一个位置不拿
同样也是对时间的浪费
注意不一定要将第i位置的宝石全拿,可以只拿一部分。
我们枚举终点,然后,双指针走起点。
*/
for (int i = 1; i <= n; i ++ ) s[i] = s[i - 1] + a[i];
int sum = 0, ans = 0;
for (int r = 1, l = 1; r <= n; r ++ ) {
sum += s[r - 1] - s[l - 1];
for (; sum > t && l < r; l ++ )
sum -= a[l] * (r - l);//满足sum<=t下,sum最大值
if (l == 1) ans = max(ans, s[r] - s[l - 1]);//sum <= t说明,可以走到r这个位置
else ans = max(ans, s[r] - s[l - 1] + (t - sum) / (r - l + 1));//
}
cout << ans << endl;
}
D减数游戏
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <vector>
using namespace std;
#define int long long
const int N = 100010, mod = 1e9 + 7;
int n, k;
int a[N];
priority_queue<int, vector<int>, greater<int>> pq;
queue<int> q;
/*
如果没有k,那么不管两数相乘的先后顺序如何,最后结果一定是n个数字的乘积。
所以,最后的结果的变化,一定是因为k的原因。那么我们要做的就是,让k对结果的影响最大。
因为a * b + k为我们处理a,b后所得的新数。我们先处理小的数,可以让k的影响更大
========
这可以通过小根堆来实现,但是,我们需要注意的一点是,每个点的是小于1e9的数,我们要对最终结果取模
但是为了不爆long long,我们要在过程中对处理的数字进行取模运算。这就可能导致原本一个比较大的值
在进行取模运算后,反而变小了,这时我们将他加入队列中,很明显,打破了我们每次取最小的原则。
=======
我们发现,当a * b + k大于数组的最大值后,每次的a * b + k一定大于序列的最大值,满足单调性。
那我们就可以将他放入普通队列中,进行取模运算了。
*/
signed main() {
scanf("%lld%lld", &n, &k);
int maxn = 0;
for (int i = 1; i <= n; i ++ ) {
scanf("%lld", &a[i]);
maxn = max(maxn, a[i]);
pq.push(a[i]);
}
while (pq.top() < maxn && pq.size() > 1) {
int t = pq.top();
pq.pop();
int s = pq.top();
pq.pop();
pq.push(t * s + k);
}
while (pq.size()) {
q.push(pq.top() % mod);
pq.pop();
}
while (q.size() > 1) {
int t = q.front();
q.pop();
int s = q.front();
q.pop();
q.push((s * t + k) % mod);
}
cout << q.front() << endl;
return 0;
}