链接:https://ac.nowcoder.com/acm/contest/23479/I
来源:牛客网
看到这个题目就能感觉到这是一道简单的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;
}
链接: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;
}
链接:https://ac.nowcoder.com/acm/contest/23479/D
来源:牛客网
简单版本:
利用三角形的角(是钝角|锐角),以及计算面积的公式( 海 伦 公 式 : 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∗(p−a)∗(p−b)∗(p−c),p=(a+b+c)/2),距离直接使用三角形的高( 2 ∗ S A B C / A B 2 2*S_{ABC}/AB2 2∗SABC/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;
}
链接: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个。
#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;
}
线段树待补