codeforces #198(div2)

怎么说呢,好不容易说半夜做,结果做了一题,碰到一道简单几何做不下去了,下面是后来参考别人的思路完成的。

参考网址:http://www.cnblogs.com/Lyush/p/3294422.html

A:太水不多说。

B:

题目大意:就是给出n个点,保证不会出现三个点在同一直线上的情况,让你从中选四个点,使形成的四边形面积最大。

解题思路:枚举一条对角线,分别枚举左边和右边的点,使左边形成的三角形最大,使右边形成的三角形也最大,这样形成的四边形面积最大。

不过有一个计算面积公式不太很明白。

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
struct Point
{
    int x,y;
}s[550];
struct Vector
{
    Point a;
    Point b;
}v;
//面积计算公式不太明白
double area(Point p1,Point p2,Point p0)
{
    return (p1.x-p0.x)*(p2.y-p0.y)-(p1.y-p0.y)*(p2.x-p0.x);
}
bool side(Point p,Vector v)
{
    return area(v.a,p,v.b)>0;
}
int main()
{
    int n;
    cin>>n;
    for(int i=0;i<n;i++)
    {
        cin>>s[i].x>>s[i].y;
    }
    double ans=0;
    for(int i=0;i<n;i++)
    {
        for(int j=i+1;j<n;j++)
        {
            double s1=0;
            double s2=0;
            v.a=s[i];
            v.b=s[j];
            for(int k=0;k<n;k++)
            {
                if(side(s[k],v))
                    s1=max(s1,fabs(area(v.a,s[k],v.b))/2);
                else
                    s2=max(s2,fabs(area(v.a,s[k],v.b))/2);
            }
            if(s1!=0&&s2!=0)
            ans=max(ans,s1+s2);
        }
    }
    printf("%lf\n",ans);
    return 0;
}


C:

题目大意:给定n个景点的位置,有一个人从0位置出发,访问景点的顺序不定,求所有情况的距离之和与所有情况个数之和   比的最简形式。

如:访问的景点位置是2 3 5

访问顺序有六种情况:


然后这题是找规律,具体规律如下:任意两个点之间的距离加上输入时输入的数字之和,

公式表示法:s1=a1+a2+....an;

                      s=s1+|ai-aj|          //注意 |a1-a2|与|a2-a1|都是要加上的。

输出s/n的最简形式。

//参考:http://blog.csdn.net/tobewhatyouwanttobe/article/details/10784873
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
__int64 a[110000],n;
__int64 ans[110000];
__int64 sum=0;
__int64 gcd(__int64 m,__int64 n)
{
    if(n==0)
        return m;
    else 
        return gcd(n,m%n);
}
void solve()
{
    for(__int64 i=2;i<=n;i++)
    {
        ans[i]=ans[i-1]+(i-1)*(a[i]-a[i-1]);
    }
    for(__int64 i=2;i<=n;i++)
    {
        sum+=ans[i]*2;
    }
}
int main()
{
    cin>>n;
    for(__int64 i=1;i<=n;i++)
    {
        cin>>a[i];
        sum+=a[i];
    }
    sort(a+1,a+1+n);
    solve();
    __int64 he=gcd(sum,n);
    cout<<sum/he<<" "<<n/he<<endl;
    return 0;
}

D:

题目大意:给定n个数字,如果第一个比第二个大,交换顺序,并且这两个数之间连一条边,问最后有多少个独立集合,即各个集合之间没有关联,  如:1 3 2     则有2 个       1和2

这个问题竟然可以转化为求最长不下降子序列,但数据量大,O(n*n)的算法不可取,所以借助了vector,复杂度只有O(n)。

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<set>
#include<map>
#include<vector>
using namespace std;
typedef vector<int> vt; //why 加 typedef
int a[110000];
int n;
void solve()
{
    vt v;
    vt::iterator it;
    for(int i=0;i<n;i++)
    {
        it=upper_bound(v.begin(),v.end(),a[i]);
        if(it==v.end())
            v.push_back(a[i]);
        else
            *it=a[i];
    }
    cout<<v.size()<<endl;
}
int main()
{
    cin>>n;
    for(int i=0;i<n;i++)
    {
        cin>>a[i];
    }
    solve();

    return 0;
}

E:  慢慢研究:

//题意:给定一个1-N的全排列,不过有些位置是被-1代替的,
//现在要求可能的原序列有多少种,
//方案数 mod 10^9+7。题目给定一个限制那就是 ai != i。
//
//分析:由于 ai != i 这完全符合错排的定义,
//不过稍有不同的此处已经给出了某些元素的位置,
//那么考虑到错排运用容斥定理的推理过程可知此处正好能够应对这一变种。
//根据输入统计出有多少个数字的安排是有限制的,多少是没有限制的。
//然后枚举有限制的数字放在限制位置的个数,容斥一下即可。

#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;

typedef long long LL;
const int N = 2005;
const int mod = int(1e9)+7;
int n, x, y; // x表示自由放置的数字的数量,y表示有限制的数字
char hav[N];
char fre[N];
int fac[N];

void pre() {
    fac[0] = 1;
    for (int i = 1; i <= 2000; ++i) {
        fac[i] = 1LL*fac[i-1]*i%mod;
    }
}

int pow(int a, int b) {
    int ret = 1;
    while (b) {
        if (b & 1) ret = 1LL*ret*a%mod;
        b >>= 1;
        a = 1LL*a*a%mod;
    }
    return ret;
}

void solve() {
    int ret = 0;
    for (int i = 0; i <= y; ++i) {
        LL sign = i & 1 ? -1 : 1;
        ret = (1LL*ret+sign*fac[x+y-i]*pow(1LL*fac[i]*fac[y-i]%mod, mod-2)%mod)%mod;
        ret = (ret + mod) % mod;
    }
    printf("%d\n", 1LL*ret*fac[y]%mod);
}

int main() {
    pre();
    int a;
    scanf("%d", &n);
    for (int i = 1; i <= n; ++i) {
        scanf("%d", &a);
        if (a != -1) hav[a] = 1, fre[i] = 1;
    }
    for (int i = 1; i <= n; ++i) {
        if (!hav[i]) {
            if (fre[i]) ++x;
            else ++y;
        }
    }
    solve();
    return 0;
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值