牛客题集:练习赛71、72

练习赛72

C

这题大概思路是想到了,但是感觉很难实现,看了眼题解,又一次学到了……

因为不能操作的时候,当且仅当一段区间变成等差数列后就不能再进行修改了,那么我们只需找到两个较小的元素,把它们中间较大元素变成等差数列就好了,但是常规写法感觉很难写。

运用几何知识,我们考虑把每个元素抽象成一个个点 ( i , x ),i是这个值在序列的位置,x是值,那么我们只需求出构成下凸包的点,把这些点连成的线,是不是就可以

看到和凸包相关的时候有点懵,但是想了想好像就是那么回事。

#include <bits/stdc++.h>
#define debug freopen("r.txt","r",stdin)
#define mp make_pair
#define ri register int
#define pb push_back
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef double lf;
typedef pair<ll, ll> pii;
const int maxn = 1e6+10;
const int N = 1500+10;
const int INF = 0x3f3f3f3f;
const int mod = 1e9+7;
const int hash_num = 131;
const double eps=1e-6;
const double PI=acos(-1.0);
inline ll read(){ll s=0,w=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
return s*w;}
ll qpow(ll p,ll q){return (q&1?p:1)*(q?qpow(p*p%mod,q/2):1)%mod;}
struct vec{
    ll x,y; vec(){} vec(ll x,ll y):x(x),y(y){}
    vec operator-(const vec &b){return vec(x-b.x,y-b.y);}
    vec operator+(const vec &b){return vec(x+b.x,y+b.y);}
    void operator+=(const vec &b){x+=b.x,y+=b.y;}
    void operator-=(const vec &b){x-=b.x,y-=b.y;}
    vec operator*(lf k){return vec(k*x,k*y);}
    bool operator==(vec b)const{return x==b.x && y==b.y;}
    ll sqr(){return x*x+y*y;}
    void output(){printf("%lld %lld\n",x,y);}
}p[maxn]; 
ll cross(vec a,vec b){return a.x*b.y-a.y*b.x;};
ll cross(vec a,vec b,vec c){return cross(a-c,b-c);}
vector<vec> st;
void push(vec &v,int b){
    while((int)st.size()>b
    && cross(*++st.rbegin(),st.back(),v)<=0) //会得到逆时针的凸包
        st.pop_back();
    st.push_back(v);
}
int n;
lf ans;
int main()
{
    #ifndef ONLINE_JUDGE
        debug;
    #endif
    n=read();
    for (int i = 1; i <= n; ++i)
    {
        p[i].x=i;
        p[i].y=read();
    }
    for (int i = 1; i <= n; ++i)
    {
        push(p[i],1);
    }
    for (int i = 1; i < st.size(); ++i)
    {
        ans+=(lf)(st[i].y+st[i-1].y)*(lf)(st[i].x-st[i-1].x+1)/2.0-(lf)(st[i].y);
    }
    ans+=(lf)st[st.size()-1].y;
    printf("%.10lf\n",ans);
    return 0;
}
View Code

 

练习赛71

B

分类讨论

唯一复杂一点的就是只有一个角的情况

如果给出的case是边角边的情况,那么肯定就只有1种,如果给出的情况是边边角的情况,那么我们就可以算出另一条边的长度,如果是等腰,就输出1,如果三边不同,就输出2,但是如果不能构成三角形就输出0.

#include <bits/stdc++.h>
#define debug freopen("r.txt","r",stdin)
#define mp make_pair
#define ri register int
#define pb push_back
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef double lf;
typedef pair<ll, ll> pii;
const int maxn = 1e6+10;
const int N = 1500+10;
const int INF = 0x3f3f3f3f;
const int mod = 1e9+7;
const int hash_num = 131;
const double eps=1e-6;
const double PI=acos(-1.0);
inline ll read(){ll s=0,w=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
return s*w;}
ll qpow(ll p,ll q){return (q&1?p:1)*(q?qpow(p*p%mod,q/2):1)%mod;}
int t,bian[5],jiao[5],sum,a[5],b[5];
int main()
{
    #ifndef ONLINE_JUDGE
        debug;
    #endif
    t=read();
    while (t--)
    {
        for (int i = 1; i <= 3; ++i) a[i]=read(),bian[i]=a[i];
        for (int i = 1; i <= 3; ++i) b[i]=read(),jiao[i]=b[i];
        sort(bian+1,bian+4);
        sort(jiao+1,jiao+4);
        reverse(bian+1,bian+4);
        reverse(jiao+1,jiao+4);
        if (bian[1]==-1)
        {
            sum=jiao[1]+jiao[2]+jiao[3];
            if (sum==180) cout << "syksykCCC"<<endl;
                else cout << 0 <<endl;
        }
        else if (bian[2]==-1)
        {
            sum=jiao[1]+jiao[2];
            if (sum>=180)cout << 0 <<endl;
            else cout << 1 <<endl;
        }
        else if (bian[3]==-1)
        {
            int q,p;
            for (int i = 1; i <= 3; ++i) if (b[i]!=-1) p=i;
            for (int i = 1; i <= 3; ++i) if (a[i]!=-1 && i!=p) q=i;
            if (a[p]==-1) cout << 1 <<endl;
            else if (jiao[1]<=90)
            {
                lf u=PI*jiao[1]/180;
                lf len=sin(u)*a[q];
                if (len - a[p] > eps) cout << 0 <<endl;
                else if (fabs(len-a[p]) <= eps) cout << 1 <<endl;
                else if (a[p]<a[q]) cout << 2 <<endl;
                else cout << 1 <<endl;
            }
            else
            {
                if (a[p]<=a[q]) cout << 0 <<endl;
                    else cout << 1 <<endl;
            }
        }
        else
        {
            if (bian[2]+bian[3]<=bian[1]) cout << 0 <<endl;
            else cout << 1 <<endl;
        }
    }
    return 0;
}
View Code

 

C

设 f[i] 表示满足了前 i-1 个条件但是第 i 个条件不满足的方案数。那么方程就是

最后答案就是所有排列的方案数减去每一个条件不满足的方案数即可。

#include <bits/stdc++.h>
#define debug freopen("r.txt","r",stdin)
#define mp make_pair
#define ri register int
#define pb push_back
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef double lf;
typedef pair<ll, ll> pii;
const int maxn = 1e6+10;
const int N = 1500+10;
const int INF = 0x3f3f3f3f;
const int mod = 20000311;
const int hash_num = 131;
const double eps=1e-6;
const double PI=acos(-1.0);
inline ll read(){ll s=0,w=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
return s*w;}
ll qpow(ll p,ll q){return (q&1?p:1)*(q?qpow(p*p%mod,q/2):1)%mod;}
ll fac[maxn],ans,f[maxn];
int a[maxn],n,m;
int main()
{
    #ifndef ONLINE_JUDGE
        debug;
    #endif
    n=read(),m=read();
    fac[0] = 1;
    for (int i = 1; i <= n; ++i)
    {
        fac[i] = fac[i-1] * i %mod;
    }
    for (int i = 1; i <= m; ++i)
    {
        a[i]=read();
    }
    sort(a+1,a+1+m);
    ans = fac[n];
    for (int i = 1; i <= m; ++i)
    {
        f[i] = fac[a[i]];
        for (int j = 1; j < i; ++j)
        {
            f[i] = (f[i]-f[j]*fac[a[i]-a[j]]%mod+mod)%mod;
        }
        ans = (ans-f[i]*fac[n-a[i]]%mod+mod)%mod;
    }
    cout << ans <<endl;
    return 0;
}
View Code

 

posted @ 2021-02-08 22:12  Y-KnightQin  阅读(68)  评论(0编辑  收藏  举报