哈理工 网络赛
大神博客 :http://m.blog.csdn.net/just_sort/article/details/78775866
题目描述
在acimo星球, tabris 是一名勇敢的屠龙勇士,在上绿岛屠龙前决定挑选N种装备武装自己,现在每种装备有两个,**但每种装备tabris必须选择拿一个**,**不能多也不能少**。
每件装备有自己的属性值,能给tabris属性加成。
对于不同种类的装备之间有叠加效果,如果选择多件装备,最终的属性加成为他们的乘积。
若tabris初始属性值为0,最后属性加成的期望是多少。
每件装备有自己的属性值,能给tabris属性加成。
对于不同种类的装备之间有叠加效果,如果选择多件装备,最终的属性加成为他们的乘积。
若tabris初始属性值为0,最后属性加成的期望是多少。
输入描述:
有多组测试样例,输入到文件结束。
每组测试数据的第一行包含一个正整数NN,表示装备的种类数。
接下来N行,每行两个正整数ai、bi,表示两个不同的第ii种装备的属性加成值。
N∈[1,103]
ai,bi∈[1,106]
输出描述:
对于每组测试数据输出一个整数,为了方便输出最终的结果先乘2N
再对1e9+7取模后的值。
示例1
输入
4 1 2 3 4 5 6 7 8
输出
3465
说明
3465 = (1*3*5*7) + (1*3*5*8) +(1*3*6*7) + (1*3*6*8) + (1*4*5*7) + (1*4*5*8) + (1*4*6*7) + (1*4*6*8) + (2*3*5*7) + (2*3*5*8) + (2*3*6*7) + (2*3*6*8) + (2*4*5*7) + (2*4*5*8) + (2*4*6*7) + (2*4*6*8) ;
题意 : 每组数据选择一个,将每组数据中选出的数据相乘,求最后的和。
思路 : 先考虑只有一组数据的情况,答案即为两个数相加的和,在考虑有两组数据的情况,在纸上写一下会发现规律,所有数据的和即为每组数据的和相乘
代码示例 :
int main() {
//freopen("in.txt", "r", stdin);
//freopen("out.txt", "w", stdout);
int n;
int a, b;
while(~scanf("%d", &n)){
ll ans = 1;
for(int i = 1; i <= n; i++){
scanf("%d%d", &a, &b);
ans *= 1ll*(a+b)%mod;
ans %= mod;
}
printf("%lld\n", ans%mod);
}
return 0;
}
c .
题目描述
小明很喜欢打游戏,现在已知一个新英雄即将推出,他同样拥有四个技能,其中三个小技能的释放时间和固定的伤害值为:
1.乌鸦坐飞机 释放时间:x 固定伤害值:a
2.蜘蛛吃耳屎 释放时间:y 固定伤害值:b
3.饿狼前进 释放时间:z 固定伤害值:c
他还有一个大招,其释放的时间是一个区间【L,R】,可以在区间内任意时间点释放出技能,其如果在L+i时刻释放技能,其能够打出的伤害值为:temp+A*i
这里temp值表示技能的基础伤害(同时也就是在时刻L释放技能的伤害值),A是一个常数。
小明很喜欢研究连招使得在有限的时间内打出最高的伤害,现在他想要在T长度单位时间内打出最高的伤害,问这个最大伤害值。
输入描述:
本题包含多组数据。
输入格式为:
T
x a
y b
z c
L R temp A
数据范围:
1<=T<=1e5
1<=x,y,z,L,R<=T
L<=R
<=a,b,c,temp,A<=1e5
输出描述:
输出包含一行,输出能够打出的最高伤害值。
示例1
输入
8 3 1 2 3 1 3 3 3 3 3
输出
24
备注:
大招:蓄力时间最短L秒,最多R秒。无限次释放,释放之后照成的伤害是随着时间增加的
蓄力L秒释放能够造成Temp的伤害
蓄力L+1秒释放能够造成Temp+1*A的伤害
依次类推
题目分析 : 如果没有大招,那这题就是一个简单的线性dp,扫一遍就过了,但是现在有大招,加了一位博友,第一次才知道,原来这种公式是可以推出来的,dp[i] = max(dp[i], dp[j]+temp+A*(i-l-j)),i-r <= j <= i-l ,维护当时间是 i 时,寻找此时的最大值并且继续更新。
但是你单纯按照着这个递推公式推,你会出错了,因为你只是确保是dp[]的最大,但是时间是不确定的,因为有可能同一个dp值,但是有两个时间都是等于这个,因此可以将公式进一步变形,dp[i] = max(dp[i], dp[j]-A*j + temp + A*(i-l)),这里可以用优先队列去维护,但是有
个点一定要知道,就是 你的时间是递推的,因此在区间内不符合范围的解,此不符合的区间的前端以后也是不会用到的,因此可以之间删除,但是后面的点以后可能会用到,要保存下来。
代码示例 :
const int eps = 1e5+5;
const double pi = acos(-1.0);
const int inf = 1<<29;
#define Max(a,b) a>b?a:b
#define Min(a,b) a>b?b:a
#define ll long long
ll dp[eps];
struct node
{
ll w;
int u;
bool operator< (const node &c)const{
return w < c.w;
}
node(ll _w, int _u):w(_w), u(_u){}
};
int main() {
//freopen("in.txt", "r", stdin);
//freopen("out.txt", "w", stdout);
int t;
int x, a, y, b, z, c;
int l, r, tem, A;
priority_queue<node>que;
stack<node>s;
//node v(0, 0);
while(~scanf("%d", &t)){
scanf("%d%d", &x, &a);
scanf("%d%d", &y, &b);
scanf("%d%d", &z, &c);
scanf("%d%d%d%d", &l, &r, &tem, &A);
while(!que.empty()) que.pop();
while(!s.empty()) s.pop();
memset(dp, 0, sizeof(dp));
ll ans = 0;
for(int i = 1; i <= t; i++){
if (i >= x) dp[i] = max(dp[i], dp[i-x]+a);
if (i >= y) dp[i] = max(dp[i], dp[i-y]+b);
if (i >= z) dp[i] = max(dp[i], dp[i-z]+c);
que.push(node(0, 0));
if (i >= l){
while(!que.empty()){
node v = que.top();
if (v.u < i-r || v.u > i-l) que.pop();
else break;
if (v.u > i-l) s.push(v);
}
node v = que.top();
dp[i] = max(dp[i], v.w+1ll*tem+1ll*A*(i-l));
//if (i == 2) printf("@@%lld %d %d %d", v.w, tem, A, i-l);
}
que.push(node(dp[i]-1ll*A*i, i));
while(!s.empty()) {
que.push(s.top());
s.pop();
}
ans = max(ans, dp[i]);
//printf("**%lld\n", dp[i]);
}
printf("%lld\n", ans);
}
return 0;
}
另一种写法 : 要好好 理解一下为什么 ret 要初始化为 long long 的负无穷
const int eps = 1e5+5;
const double pi = acos(-1.0);
const int inf = 1<<29;
#define Max(a,b) a>b?a:b
#define Min(a,b) a>b?b:a
#define ll long long
ll dp[eps];
struct node
{
int l, r, k;
ll w;
}tree[eps<<2];
ll maxx;
void build(int l, int r, int k){
tree[k].l = l, tree[k].r = r;
if (l == r){
tree[k].w = 0;
return;
}
int m = (l + r)>>1;
build(l, m, k<<1);
build(m+1, r, k<<1|1);
tree[k].w = max(tree[k<<1].w,tree[k<<1|1].w);
}
ll query(int L, int R, int k){
if (L <= tree[k].l && tree[k].r <= R){
return tree[k].w;
}
int m = (tree[k].l + tree[k].r) >> 1;
ll ret = -__LONG_LONG_MAX__; // 初始化为long long 的负无穷
if (L <= m) ret = max(ret, query(L, R, k<<1));
if (R > m) ret = max(ret, query(L, R, k<<1|1));
return ret;
}
void update(int pos, ll val, int k){
if (tree[k].l == tree[k].r){
tree[k].w = val;
return;
}
int m = (tree[k].l + tree[k].r) >> 1;
if (pos <= m) update(pos, val, k<<1);
else update(pos, val, k<<1|1);
tree[k].w = max(tree[k<<1].w,tree[k<<1|1].w);
}
int main() {
//freopen("in.txt", "r", stdin);
//freopen("out.txt", "w", stdout);
int t;
int x, a, y, b, z, c;
int l, r, tem, A;
while(~scanf("%d", &t)){
scanf("%d%d", &x, &a);
scanf("%d%d", &y, &b);
scanf("%d%d", &z, &c);
scanf("%d%d%d%d", &l, &r, &tem, &A);
memset(dp, 0, sizeof(dp));
build(0, t, 1);
ll ans = 0;
for(int i = 1; i <= t; i++){
if (i >= x) dp[i] = max(dp[i], dp[i-x]+a);
if (i >= y) dp[i] = max(dp[i], dp[i-y]+b);
if (i >= z) dp[i] = max(dp[i], dp[i-z]+c);
if (i >= l) {
int L = i - r, R = i - l;
if (L < 0) L = 0;
dp[i] = max(dp[i], query(L, R, 1)+1ll*tem+1ll*A*(i-l));
}
update(i, dp[i]-1ll*A*i, 1);
ans = max(ans, dp[i]);
}
printf("%lld\n", ans);
}
return 0;
}
东北日出西边雨 道是无情却有情

浙公网安备 33010602011771号