codeforces #198(div2)

caoxiaoran1202發表於2013-09-03

怎麼說呢,好不容易說半夜做,結果做了一題,碰到一道簡單幾何做不下去了,下面是後來參考別人的思路完成的。

參考網址: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;
}




相關文章