版权声明:吸吸 https://blog.csdn.net/walk_dog/article/details/80958589
T1
OJ传送门
洛谷传送门
这道题当时快速幂的模板写错了,很震惊居然还能拿到60分
然后就是广为人知的数学选修2-3的二项式定理,如果我没记错的话,是这样的:
那这道题最重要的一行代码就是:int ans=power(a,n)*power(b,m)%mod*C(k,m)%mod;
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
const ll MOD = 10007;
ll rec[1010][1010];
ll a,b,k,n,m;
ll C(ll n,ll r)
{
if(n==r || r==0) return rec[n][r]=1;
if(rec[n][r]) return rec[n][r];
return rec[n][r] = (C(n-1,r)+C(n-1,r-1)) % MOD;
}
ll power(ll x, ll k)
{
ll ans = 1;
while(k)
{
if(k & 1) ans = ans * x % MOD;
x = x * x % MOD;
k >>= 1;
}
return ans;
}
int main()
{
scanf("%lld%lld%lld%lld%lld", &a, &b, &k, &n, &m);
ll ans = power(a, n) * power(b, m) % MOD * C(k, m) % MOD;
printf("%lld",ans);
return 0;
}
T2
OJ传送门
这道题用二分和前缀和的做法,在最大质量和最小质量中间二分,但为了避免忘记特判特殊端点,二分的真正范围是max_weight+2与min_weight-1之间。具体思想是,W越小,Y越大;W越大,Y越小。当Y>S时,我们要增大W的值,使abs(Y-S)变小,反之同理。
维护前缀和就维护pre_v[i]维护到第i个矿石时满足条件的所有矿石的价值,pre_cnt[i]维护的是前i个矿石符合条件的矿石数。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
const int MAXN = 2e5+5;
ll n, m, S, l_i, r_i;
ll max_weight = -1, min_weight = 99999999;
ll Y, sum, answer;
ll l[MAXN], r[MAXN];
ll w[MAXN], v[MAXN], pre_v[MAXN], pre_cnt[MAXN];
bool check(ll W)
{
memset(pre_v, 0, sizeof(pre_v));
memset(pre_cnt, 0, sizeof(pre_cnt));
Y = 0, sum = 0;
for(ll i = 1; i <= n; i++)
{
if(w[i] >= W)
{
pre_v[i] = pre_v[i-1] + v[i];
pre_cnt[i] = pre_cnt[i-1] + 1;
} else {
pre_v[i] = pre_v[i-1];
pre_cnt[i] = pre_cnt[i-1];
}
}
for(ll i = 1; i <= m; i++)
Y += (pre_cnt[r[i]] - pre_cnt[l[i]-1]) * (pre_v[r[i]] - pre_v[l[i]-1]);
sum = llabs(Y - S);
if(Y > S) return true;
else return false;
}
int main()
{
// freopen("qc.in","r",stdin);
// freopen("qc.out","w",stdout);
scanf("%lld%lld%lld", &n, &m, &S);
for(ll i = 1; i <= n; i++)
{
scanf("%lld%lld", &w[i], &v[i]);
max_weight = max(max_weight, w[i]);
min_weight = min(min_weight, w[i]);
}
for(ll i = 1; i <= m; i++)
scanf("%lld%lld", &l[i], &r[i]);
ll left = min_weight-1, right = max_weight+2;
ll answer = 99999999999;
while(left<=right)
{
ll mid = (left+right) >> 1;
if(check(mid)) left = mid+1;
else right = mid-1;
if(sum < answer) answer = sum;
}
printf("%lld", answer);
return 0;
}