atcoder arc 122 a~b题Many FormulaeInsurance

Posted 要坚持写博客

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了atcoder arc 122 a~b题Many FormulaeInsurance相关的知识,希望对你有一定的参考价值。

A题链接
题目大意:不能存在两个及两个以上的减号,所有满足条件的式子之和。
题目思路:当时考试想到一半,就感觉编码能力不太会,然后就没做,
首先我们定义dp[N][2],这种选或不选的问题,一般都是这样定义的;
其中:dp[i][0]表示第i个为+,(这里我们可以把每个数看成是一个符号,自己在第一个数前面加了一个+。)因为这样看比较容易一点。
dp[i][1]表示第i个为-;当时就想到这里。但是没去写…………
这时候成功了一半了,然后我们还需要定义一个cnt[i][2]去记录数量,cnt[i][0]表示第i个数为+的数量,cnt[i][1]表示第i个数为-的数量。

此时我们可以写出dp式子了。
cnt[i][0]=cnt[i-1][0]+cnt[i-1][1];
cnt[i][1]=cnt[i][0];
dp[i][0]=dp[i-1][1]+dp[i-1][0]+cnt[i][0]*a[i];
dp[i][1]=dp[i-1][0]-cnt[i][1]*a[i];
最后的答案就是dp[n][0]+dp[n][1]了,

代码如下:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
#include<math.h>
#include<iostream>
#include<cmath>
#include<queue>
#include<vector>
#define IOS ios::sync_with_stdio(false);cin.tie();cout.tie(0)

using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pll;
const int N=1e5+10;
const int mod=1e9+7;
ll a[N];
ll dp[N][2],cnt[N][2];

int main()
{
    IOS;
    ll n;
    cin>>n;
    for(int i=1;i<=n;i++)
        cin>>a[i];
    dp[1][0]=a[1];
    dp[1][1]=0;
    cnt[1][0]=1;
    cnt[1][1]=0;
    for(int i=2;i<=n;i++)
    {
        cnt[i][0] = (cnt[i-1][0]%mod +cnt[i-1][1]%mod)%mod;
        cnt[i][1] = cnt[i-1][0]%mod;
        dp[i][0]=(dp[i-1][0]%mod+dp[i-1][1]%mod+cnt[i][0]*a[i]+mod)%mod;
        dp[i][1]=(dp[i-1][0]%mod-cnt[i][1]*a[i]%mod+mod)%mod;
    }
    cout<<(dp[n][0]+dp[n][1])%mod<<endl;
    return 0;
}

B题链接
题目大意,投资x元,亏了。对每个a[i]只会赔偿min(a[i],2x);
也就是最后题目给的那个式子:x+a[i]-min(a[i],2
x);
求他亏钱最小,看案例一。

题目思路:从最后一个式子入手。这里我们排序之后对结果没有影响,但对我们的思路有利,就先排个序。排序之后我们枚举每一个a[i]的一半,都存在下面那个式子,这里为什么a[i]一半是对的呢?这里我们整体,如果后面那部分个数多,这里x肯定会是在a[i]/2a[i+1]/2之间取,我们最后肯定是后面那部分累加还有先低效前面x再减去x使得累计和最小。如果前面那部分多,我们最后是后面那部分累加之后再加上x,这里x肯定会是在a[i]/2a[i+1]/2之间取
加个图片好理解

代码如下:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
#include<math.h>
#include<iostream>
#include<cmath>
#include<queue>
#include<vector>
#define IOS ios::sync_with_stdio(false);cin.tie();cout.tie(0)

using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pll;
const int N=1e5+10;
const int mod=1e9+7;
double a[N],s[N];

int main()
{
    IOS;
    int n;
    cin>>n;
    double n1=n*1.0;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
    }
    sort(a+1,a+n+1);
    for(int i=1;i<=n;i++)
    {
        s[i]=s[i-1]+a[i];
    }
    double sum=0x3f3f3f3f;//0x3f3f3f3f的十进制是1061109567,所以sum更新的时候就除以n1了,不然这数据范围满足不了
    for(int i=1;i<=n;i++)
    {

        double w=a[i]/2;
        double w1=(s[n]-s[i])-(n-i-i)*w;
        sum=min(sum,w1/n1);
    }
    printf("%.6lf",sum);
    return 0;
}

以上是关于atcoder arc 122 a~b题Many FormulaeInsurance的主要内容,如果未能解决你的问题,请参考以下文章

ARC122A Many Formulae 题解

Plus Matrix atcoder arc115 TB

Plus Matrix atcoder arc115 TB

ARC122CCalculator

atcoder ARC092 D - Two Sequences 二分 & 二进制

ARC122C-Calculator乱搞,构造