第十周周赛——周赛兼组队赛第二场题解(出自 BNUOJ28207,BNUOJ28201,BNUOJ28209,codeforces 667B,HDU 5439,HDU 5478)

A题:

A题题目链接

题目描述:

Star

TimeLimit: 1000ms  MemoryLimit:32768KB
64-bit integer IO format: %I64d
Problem Description
Overpower often go to the playground with classmates. They play and chat on the playground. One day, there are a lot of stars in the sky. Suddenly, one of Overpower’s classmates ask him: “How many acute triangles whose inner angles are less than 90 degrees (regarding stars as points) can be found? Assuming all the stars are in the same plane”. Please help him to solve this problem.
Input

The first line of the input contains an integer T (T≤10), indicating the number of test cases.

For each test case:

The first line contains one integer n (1≤n≤100), the number of stars.

The next n lines each contains two integers x and y (0≤|x|, |y|≤1,000,000) indicate the points, all the points are distinct.

Output
For each test case, output an integer indicating the total number of different acute triangles.
SampleInput
1
3
0 0
10 0
5 1000
SampleOutput
1
题意:

给定n个点,计算这n个点能够构成多少个锐角三角形。

解析:

由于题目数据很小,n<=100,因此考虑暴力。

判断锐角三角形,我们很容易想到余弦定理:

a^2 + b^2 - c^2 = 2 * a * b * cos a(a指的是角A)

而要是锐角三角形,那么cos a必然是大于0的,则要满足:

a^2 + b^2 > c^2 

因此我们只需要将所有的边都计算出来,然后暴力枚举即可。

这里要注意的两个问题:

1.注意特判三点共线的问题

2.由于不确定三条边的长短次序,因此本应该枚举三种边的情况都满足,但是如果最小的一组边的平方和满足的话,其余两组也都

满足的。比如说,计算得a^2,b^2为较小的那两条边的平方,那么只需满足a^2 + b^2 > c^2 这一组情况即可。

这时候你应该注意到了一个问题,为什么不用判断构成三角形的问题?

由于构成三角形的要素是任意两边之和大于第三边,那么很明显只要最小的两条边大于第三边即可。

显然在上面计算得a^2,b^2为较小的那两条边的平方,a,b这两边是较小的两条边,那么如果要构成三角形,必然满足a + b > c

左右两边平方,即a^2 + 2*a*b + b^2 > c^2.而在上面我们统计的情况中,需要满足的条件是a^2 + b^2 > c^2,而条件a^2 + b^2 > 

c^2成立的话,由于a,b > 0,显然a^2 + 2*a*b + b^2 > c^2也是成立的,因此不必再判断构成三角形的问题。

最后我们要将统计好的结果除以6,原因是对于任意的三个能够构成锐角三角形的点,这个三角形总共计算的次数为C(3,1) * C(2,

1) * C(1,1) = 6,而结果只是1种,因此我们要将将统计好的结果除以6即得最后的总三角形数目。

完整代码实现:

#include
#include
#include

using namespace std;
typedef long long LL;
const int MAX_N = 105;
LL x[MAX_N],y[MAX_N];

void solve(){
    int T,n;
    scanf("%d",&T);
    while(T--){
        scanf("%d",&n);
        for(int i = 0;i < n;++i){
            scanf("%I64d %I64d",&x[i],&y[i]);
        }
        LL ans = 0;
        for(int i = 0;i < n;++i){
            for(int j = 0;j < n;++j){
                if(i == j){
                    continue;
                }
                for(int k = 0;k < n;++k){
                    if(i == k || j == k){
                        continue;
                    }
                    LL tmp1 = (y[j] - y[i]) * (x[i] - x[k]);
                    LL tmp2 = (y[i] - y[k]) * (x[j] - x[i]);
                    if(abs(tmp1) == abs(tmp2)){
                        continue;
                    }
                    LL a = (y[j] - y[i]) * (y[j] - y[i]) + (x[j] - x[i]) * (x[j] - x[i]);
                    LL b = (y[k] - y[i]) * (y[k] - y[i]) + (x[k] - x[i]) * (x[k] - x[i]);
                    LL c = (y[j] - y[k]) * (y[j] - y[k]) + (x[j] - x[k]) * (x[j] - x[k]);
                    LL min_Num = min(min(a,b),c);
                    LL max_Num = max(max(a,b),c);
                    LL sec_Num = a + b + c - min_Num - max_Num;
                    if((min_Num + sec_Num) > max_Num){
                        ++ans;            //细节...别着急交...
                    }
                }
            }
        }
        printf("%I64d\n",ans / 6);
    }
}
int main(){
    solve();
    return 0;
}
B题:

B题题目链接

题目描述:

Floor problem

TimeLimit: 1000ms  MemoryLimit:32768KB
64-bit integer IO format: %I64d
Problem Description

In this problem, we have f(n,x)=Floor[n/x]. Here Floor[x] is the biggest integer such that no larger than x. For example, Floor[1.1]=Floor[1.9]=1, Floor[2.0]=2.

You are given 3 positive integers n, L and R. Print the result of f(n,L)+f(n,L+1)+...+f(n,R), please.

Input

The first line of the input contains an integer T (T≤100), indicating the number of test cases.

Then T cases, for any case, only 3 integers n, L and R (1≤n, L, R≤10,000, L≤R).

Output
For each test case, print the result of f(n,L)+f(n,L+1)+...+f(n,R) in a single line.
SampleInput
3
1 2 3
100 2 100
100 3 100
SampleOutput
0
382
332
解析:

题意不多说,题目描述得非常清晰,范围很小,直接暴力计算即可。

完整代码实现:

#include
int main(){
    int T,n,L,R;
    scanf("%d",&T);
    while(T--){
        scanf("%d %d %d",&n,&L,&R);
        int ans = 0;
        for(int i = L;i <= R;++i){
            ans += (int)(n/i);
        }
        printf("%d\n",ans);
    }
    return 0;
}

D题:

D题题目链接
题目描述:

Coat of Anticubism

TimeLimit:1000MS  MemoryLimit:256MB
64-bit integer IO format: %I64d
Problem Description

As some of you know, cubism is a trend in art, where the problem of constructing volumetrical shape on a plane with a combination of three-dimensional geometric shapes comes to the fore.

A famous sculptor Cicasso, whose self-portrait you can contemplate, hates cubism. He is more impressed by the idea to transmit two-dimensional objects through three-dimensional objects by using his magnificent sculptures. And his new project is connected with this. Cicasso wants to make a coat for the haters of anticubism. To do this, he wants to create a sculpture depicting a well-known geometric primitive — convex polygon.

Cicasso prepared for this a few blanks, which are rods with integer lengths, and now he wants to bring them together. Thei-th rod is a segment of length li.

The sculptor plans to make a convex polygon with a nonzero area, using all rods he has as its sides. Each rod should be used as a side to its full length. It is forbidden to cut, break or bend rods. However, two sides may form a straight angle .

Cicasso knows that it is impossible to make a convex polygon with a nonzero area out of the rods with the lengths which he had chosen. Cicasso does not want to leave the unused rods, so the sculptor decides to make another rod-blank with an integer length so that his problem is solvable. Of course, he wants to make it as short as possible, because the materials are expensive, and it is improper deed to spend money for nothing.

Help sculptor!

Input

The first line contains an integer n (3 ≤ n ≤ 105) — a number of rod-blanks.

The second line contains n integers li (1 ≤ li ≤ 109) — lengths of rods, which Cicasso already has. It is guaranteed that it is impossible to make a polygon with n vertices and nonzero area using the rods Cicasso already has.

Output

Print the only integer z — the minimum length of the rod, so that after adding it it can be possible to construct convex polygon with (n + 1) vertices and nonzero area from all of the rods.

SampleInput 1
3
1 2 1
SampleOutput 1
1
SampleInput 2
5
20 4 3 2 1
SampleOutput 2
11
 
    
Note

In the first example triangle with sides {1 + 1 = 2, 2, 1} can be formed from a set of lengths {1, 1, 1, 2}.

In the second example you can make a triangle with lengths {20, 11, 4 + 3 + 2 + 1 = 10}.

题意:

这道题其实是道水题,但是题意很唬人,不过看懂了就秒AC了~

建议可以从Note入手。

其实题目能够转换成简单的构建三角形的问题,当最长边大于等于剩余边之和时,这时候就无法构建三角形了,因此要借助另外的

木棍,而借助的木棍最短长度显然是最长边 - 剩余边之和 + 1.而当最长边小于剩余边之和时,则不必另外借助木棍,直接就能够构

成三角形,则另外需要的木棍长度为0.

完整代码实现:

#include
#include
using namespace std;
typedef long long ll;
int main(){
    ll n,num,Max = 0,ans = 0;
    scanf("%I64d",&n);
    for(int i = 1;i <= n;++i){
        scanf("%I64d",&num);
        Max = max(Max,num);
        ans += num;
    }
    printf("%I64d\n",(ans - Max > Max) ? 0 : 2*Max-ans + 1);
    return 0;
}


F题:

F题题目链接

题目描述:

Can you find it

TimeLimit:5000MS  MemoryLimit:65536KB
64-bit integer IO format: %I64d
Problem Description

Given a prime number C(1 <= C <= 2 * 10^5), and three integers k1, b1, k2 (1 <= k1, k2, b1 <= 10^9). Please find all pairs (a, b) which satisfied the equation .

Input
There are multiple test cases (no more than 30). For each test, a single line contains four integers C, k1, b1, k2.
Output

First, please output "Case #k: ", k is the number of test case. See sample output for more detail.
Please output all pairs (a, b) in lexicographical order. (1 <= a, b < C). If there is not a pair (a, b), please output -1.

SampleInput
23 1 1 2
SampleOutput
Case #1:
1 22
解析:

其实这道题目并不难!!不过题目给的公式够唬人的!!由于这个公式对n(1,2,3,4...)均成立,那么当没有头绪的时候,我们可以枚

举前几项,看看能否找到一般规律。

当n = 1时,则有:

(a^(k1+b1) + b)mod c = 0;                -----------(1)

当n = 2时,则有:

(a^(2 * k1+b1) + b^(k2+1))mod c = 0;             -------------(2)

这时候我们发现第一项和第二项出现了能够抵消的部分。因此我们可以将(1)* a^k1,则有

(a^(2 * k1+b1) + b * a^k1)mod c = 0; --------------(3)

根据同余定理,我们将(2),(3)式括号里面的式子展开,则可得到

 b^(k2+1) mod c = (b * a^k1)mod c

而b != 0,两边同时除以b,则有:

b ^ k2 mod c =a^k1 mod c --------------(4)

因此,式子推导到这里,做法就很明朗了。符合条件的(a,b)只需满足:b ^ k2 mod c = a^k1 mod c

但是由于a,b范围较大,如果直接用两层for循环暴力找的话,显然会超时的,因此我们可以利用这里已有的等式,找到符合条件的(a,b)

组合。

一开始的时候,我们可以用快速幂计算得a^k1 mod c 的值,然后再利用等式(1),即可计算得b = c -a^k1 mod c.

而后同样利用快速幂计算b ^ k2 mod c的值,如果b ^ k2 mod c =a^k1 mod c 相等的话,则将该(a,b)输出。

完整代码实现:

#include
typedef long long ll;
ll quick_power(ll base,ll radix,ll mod){
    ll ans = 1;
    while(radix){
        if(radix&1){
            ans = ans * base % mod;
        }
        base = base * base % mod;
        radix >>= 1;
    }
    return ans % mod;
}
void solve(){
    ll c,k1,b1,k2,flag = 1;
    while(scanf("%I64d %I64d %I64d %I64d",&c,&k1,&b1,&k2)==4){
        printf("Case #%I64d:\n",flag++);
        bool has_Pair = false;
        for(ll i = 1;i < c;++i){
            ll left = quick_power(i,k1,c);
            ll temp = c - quick_power(i,k1+b1,c);
            ll right = quick_power(temp,k2,c);
            if(left == right){
                has_Pair = true;
                printf("%I64d %I64d\n",i,temp);
            }
        }
        if(!has_Pair){
            printf("-1\n");
        }
    }
}
int main(){
    solve();
    return 0;
}

总结:做题不可急躁,要看清楚输出约束以及题目中的边界条件,不要因为水题而卡了罚时,宁愿多检查一分钟,也不慌乱提

交。

你可能感兴趣的:(fjut,ACM集训队周赛题解)