2020牛客寒假算法基础集训营2

B

https://ac.nowcoder.com/acm/contest/3003/C

思路:

一开始不懂概率模意义下的运算,然后学了一波,例如原来是二分之一乘以二分之一,那么乘起来就是四分之一,那么模意义下也是直接相乘,但是记得模,然后就是1-二分之一,变成模的意义下就是mod-模意义下的概率+1;

接下来就是本题重点,dp

恰好有k个题目过范围大的话一个一个枚举就会爆掉,所以dp意义下,我们设dp【i】【j】意义是

i道题目恰好j道题过的概率;

显然

f[0][j] ={1,j=0;

   {0,j>0;

x显然

f[i][j] ={f[i-1][j]*(1-pi),j=0;

   {f[i-1][j-1]*pi+f[i-1][j]*(1-pi),j>0;

#include 
#define maxn 2020
using namespace std;
typedef long long ll;
const int mod=1000000007;
int n,a[maxn];
ll dp[maxn][maxn];
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    dp[0][0]=1;

    for(int i=1;i<=n;i++){
        dp[i][0]=(dp[i-1][0]*(mod-a[i]+1))%mod;
        for(int j=1;j<=i;j++)
            dp[i][j]=((dp[i-1][j]*(mod-a[i]+1)%mod)+(dp[i-1][j-1]*a[i]%mod))%mod;
    }
//    double ans=0;
    for(int i=0;i<=n;i++) cout< 
 

 给出坐标,求能构成多少个锐角三角形

我刚开始的时候想的是枚举钝角和直角
然后计算每三个点能组成的三角形的个数
减去共线的,再减去钝角和直角的个数,即为答案
而且我在极角排序之后,我试图用二分来确定上下界
这样也不是不能做,但是比较麻烦

题解的方法就比较好
统计锐角的个数,设为 AA,钝角和直角的个数,设为 BB
每个锐角三角形有三个锐角,每个钝角和直角三角形均贡献两个锐角
所以答案即为 A−2B3

#include
using namespace std;
typedef long long ll;
const double pi=acos(-1.0);
const double eps=1e-9;
int n;
struct node1
{
    double x,y;
}a[2010];
double node[4010];
int main()
{
    while(scanf("%d",&n)!=EOF)
    {
        for(int i=1;i<=n;i++)scanf("%lf%lf",&a[i].x,&a[i].y);
        ll ans1=0,ans2=0;
        for(int i=1;i<=n;i++)
        {
            int cnt=0;
            for(int j=1;j<=n;j++)
            {
                if(i==j)continue;
                node[++cnt]=atan2(a[i].y-a[j].y,a[i].x-a[j].x);
                if(node[cnt]<0)node[cnt]+=2*pi;
            }
            sort(node+1,node+1+cnt);
            for(int j=1;j<=cnt;j++)node[j+cnt]=node[j]+2*pi;
            int l=1,r=1,len=1;
            for(int j=1;j<=cnt;j++)
            {
                while(r<=2*cnt&&node[r]-node[j] 
 

  求有多少个钝角三角形

#include
using namespace std;
typedef long long ll;
const double pi=acos(-1.0);
const double eps=1e-9;
int n;
struct node1
{
    double x,y;
}a[2010];
double node[4010];
int main()
{
    while(scanf("%d",&n)!=EOF)
    {
        for(int i=1;i<=n;i++)scanf("%lf%lf",&a[i].x,&a[i].y);
        ll ans1=0,ans2=0;
        for(int i=1;i<=n;i++)
        {
            int cnt=0;
            for(int j=1;j<=n;j++)
            {
                if(i==j)continue;
                node[++cnt]=atan2(a[i].y-a[j].y,a[i].x-a[j].x);
                if(node[cnt]<0)node[cnt]+=2*pi;
            }
            sort(node+1,node+1+cnt);
            for(int j=1;j<=cnt;j++)node[j+cnt]=node[j]+2*pi;
            int l=1,r=1,len=1;
            for(int j=1;j<=cnt;j++)
            {
                while(r<=2*cnt&&node[r]-node[j] 
 

  链接:https://ac.nowcoder.com/acm/contest/3003/E
两边平方,就成了i+j+2根号ij=k,那么就是要使ij为完全平方数,也就是可以被根号出整数

#include
using namespace std;
typedef long long ll;
int main()
{
    ll n;
    scanf("%lld",&n);
    ll ans=0;
    for(ll i=1;i*i<=n;i++){
        ll x=i*i;
        for(ll j=1;j*j<=x;j++){
            if(x%j==0){
                ans++;
                if(j*j!=x)ans++;
            }
        }
    }
    printf("%lld\n",ans);
    return 0;
}

  https://ac.nowcoder.com/acm/contest/3003/F

切勿被最优策略给骗了,说是最优,这样看你拿了这个物品,这个物品的ai和bi都到你手上了,你的模板是和对方拉分最大,所以实际上bi这个分数他拿不了了

用人话说你每次拿了一个物品计分ai但同时也剥夺了他拿bi的机会们,也就是拉分了ai+bi,故可以以ai+bi为排序

#include
#define maxn 200010
using namespace std;
 
int n;
struct Node{
    int posA,posB;
}a[maxn];
 
struct New{
    int key,pos;
}b[maxn];
 
bool cmp(New x,New y){
    return x.pos>y.pos;
}
 
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;++i)
        scanf("%d",&a[i].posA);
    for(int i=1;i<=n;++i){
        scanf("%d",&a[i].posB);
        b[i].pos=a[i].posA+a[i].posB;
        b[i].key=i;
    }
    sort(b+1,b+n+1,cmp);
    for(int i=1;i<=n;++i)
        if(i&1)
            printf("%d ",b[i].key);
    printf("\n");
    for(int i=1;i<=n;++i)
        if(!(i&1))
            printf("%d ",b[i].key);
    return 0;
}

  H

思路:直接

f[i]表示前ii个元素以ii为尾划分段后的最小值
也就是f[i]可以作为前面的一段的末尾,或者和前面的k-1个构成新的一段k,

#include
#define maxn 200010
using namespace std;
 
int n;
struct Node{
    int posA,posB;
}a[maxn];
 
struct New{
    int key,pos;
}b[maxn];
 
bool cmp(New x,New y){
    return x.pos>y.pos;
}
 
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;++i)
        scanf("%d",&a[i].posA);
    for(int i=1;i<=n;++i){
        scanf("%d",&a[i].posB);
        b[i].pos=a[i].posA+a[i].posB;
        b[i].key=i;
    }
    sort(b+1,b+n+1,cmp);
    for(int i=1;i<=n;++i)
        if(i&1)
            printf("%d ",b[i].key);
    printf("\n");
    for(int i=1;i<=n;++i)
        if(!(i&1))
            printf("%d ",b[i].key);
    return 0;
}

  

 

你可能感兴趣的:(2020牛客寒假算法基础集训营2)