2022 牛客寒假训练营4

I-爆炸的符卡洋洋洒洒

题目描述:

链接:https://ac.nowcoder.com/acm/contest/23479/I
来源:牛客网
2022 牛客寒假训练营4_第1张图片

主要思路:

看到这个题目就能感觉到这是一道简单的01背包问题,也想到了需要%k那样来写状态转移方程,但是由于实在是不会做dp的题目,还是给写挂了

#include
#include
#include
using namespace std;
typedef long long ll;
ll s[1010],w[1010];
ll f[1010][1010];
int main()
{
    int n,k;
    cin>>n>>k;
    for(int i=1;i<=n;i++) cin>>s[i]>>w[i];
    memset(f,-0x3f3f,sizeof(f));
    f[0][0]=0;
    for(int i=1;i<=n;i++)
    {
        for(int j=0;j<k;j++)
        {
            f[i][j]=f[i-1][j];
            f[i][j]=max(f[i][j],f[i-1][(j-s[i]%k+k)%k]+w[i]);
        }
    }
    if(f[n][0]<=0) f[n][0]=-1;
    cout<<f[n][0]<<endl;
    return 0;
}

A-R

题目描述:

链接:https://ac.nowcoder.com/acm/contest/23479/A
来源:牛客网

小红拿到了一个长度为 nn 的字符串,该字符串仅由大写字母组成。
小红很喜欢红色(用’R’字母表示),但她非常讨厌紫色(用’P’字母表示)。
她想取一个连续子串,该子串包含至少 kk 个’R’字符,且不能包含’P’字符。
你能告诉她有多少合法的方案可以取到吗?
注:只要连续子串的起始位置或终止位置不同,我们就认为是两个不同的方案。

主要思路:

化整为0

由于最终求的字符串不能包含字母’P’,所以我们可以根据初始的’P’字符先将字符串切成很多小字符串。

然后问题就变成了,求一个字符串,有多少字符至少包含了 k个 ‘R’。

这个问题如果枚举左端点,显然右端点是满足单调性的。可以用二分或者双指针来求出右端点的位置。

总复杂度为 O(n)

#include
#include
#include
using namespace std;
typedef long long ll;
ll n,k,ans;
void get(string s)
{
    int nr=0,j=0;
    for(int  i=0;i<s.size();i++)
    {
        nr+=s[i]=='R';
        while(j<=i&&nr>=k)
            nr-=s[j++]=='R';
        ans+=j;
    }
}
int main()
{
    cin>>n>>k;
    string s;
    cin>>s;
    string ss="";
    for(int i=0;i<n;i++)
    {
        if(s[i]=='P') get(ss),ss="";
        else ss+=s[i];
    }
    get(ss);
    cout<<ans<<endl;
    return 0;
}

D-雪色光晕

题目描述:

链接:https://ac.nowcoder.com/acm/contest/23479/D
来源:牛客网
2022 牛客寒假训练营4_第2张图片

主要思路:

简单版本:
利用三角形的角(是钝角|锐角),以及计算面积的公式( 海 伦 公 式 : S = p ∗ ( p − a ) ∗ ( p − b ) ∗ ( p − c ) , p = ( a + b + c ) / 2 海伦公式:S=\sqrt{p*(p-a)*(p-b)*(p-c)},p=(a+b+c)/2 S=p(pa)(pb)(pc) ,p=(a+b+c)/2),距离直接使用三角形的高( 2 ∗ S A B C / A B 2 2*S_{ABC}/AB2 2SABC/AB2)。

#include
#include
#include
#include
using namespace std;
double get(double x,double y,double x0,double y0)
{
    double ans=sqrt((x-x0)*(x-x0)+(y-y0)*(y-y0));
    return ans;
}
int main()
{
    int n;
    cin>>n;
    double x,y,x0,y0,xx,yy;
    cin>>x>>y>>x0>>y0;
    double ans=sqrt((x-x0)*(x-x0)+(y-y0)*(y-y0));
    while(n--)
    {
        double dx,dy;
        cin>>dx>>dy;
        xx=x+dx,yy=y+dy;
        double a=get(x0,y0,x,y),b=get(x0,y0,xx,yy),c=get(x,y,xx,yy);
        if(a*a+c*c>b*b&&c*c+b*b>a*a)// 存在垂直距离
        {
            double p=(a+b+c)/2.0;
            double s=sqrt(p*(p-a)*(p-b)*(p-c));
            ans=min(ans,2*s/c);
        }
        else ans=min(ans,min(a,b));
        x=xx,y=yy;
    }
    printf("%.9lf\n",ans);
    return 0;
}

G-子序列权值乘积

题目描述:

链接:https://ac.nowcoder.com/acm/contest/23479/G
来源:牛客网

小红定义一个数组的权值为该数组的最大值乘以最小值。例如数组 [4,1,3] 的权值是 4*1=4。
小红拿到了一个数组。她想知道,这个数组的所有 非空子序列 的权值的乘积是多少?由于该数过大,请对1000000007取模。
子序列的定理:对于一个数组,删除其中某些数之后(也可以不删)得到的数组。子序列中的数的相对顺序必须和原数组中的顺序相同。
例如:数组 [1,3,2] 的非空子序列有 [1] [3] [2] [1,3] [1,2] [3,2] [1,3,2] 共7个。

主要思路:

方法一:
2022 牛客寒假训练营4_第3张图片

#include
#include
#include
using namespace std;
typedef long long ll;
const int N=2e5+10,mod=1e9+7;
ll a[N];
ll qpow(ll a,ll b,ll mod)
{
    ll ans=1;
    while(b)
    {
        if(b&1) ans=(ans*a)%mod;
        b>>=1;
        a=(a*a)%mod;
    }
    return ans;
}
int main()
{
    int n;
    cin>>n;
    ll ans=1,tmp=1;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
        ans=ans*a[i]%mod*a[i]%mod;
    }
    tmp=ans;
    sort(a+1,a+n+1);
    int l=1,r=n;
    while(l<n)
    {
        tmp=tmp*qpow(a[l++],mod-2,mod)%mod*qpow(a[r--],mod-2,mod)%mod;
        ans=qpow(tmp%mod,qpow(2,l-2,mod-1),mod)%mod*ans%mod;
    }
    cout<<ans<<endl;
    return 0;
}

方法二:
2022 牛客寒假训练营4_第4张图片

B-进制

线段树待补

你可能感兴趣的:(动态规划,算法,c++)