1. 程式人生 > 實用技巧 >2020 年百度之星·程式設計大賽 - 初賽二

2020 年百度之星·程式設計大賽 - 初賽二

Poker

Time Limit: 2000/1000 MS (Java/Others)Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 98Accepted Submission(s): 39

傳送門

Problem Description 小沃沃在玩一個有趣的遊戲。

初始他有n塊錢,每一輪他需要投入至少m塊錢,系統會拿走其中p%的錢,並把剩下的錢還給他。

請問在最優情況下,小沃沃最多可以玩多少輪?

假設當前一輪小沃沃投入了x塊錢,那麼他可以收回x×(1p%)塊錢,其中a
表示a取下整。
小沃沃每一輪投入的錢不能超過他現在擁有的錢。

每一輪投入的錢必須為整數。

Input 第一行一個正整數test(1test100000)表示資料組數。

對於每組資料,一行三個整數n,m,p(1n100000,1m1000,1p100)

Output 對每組資料輸出一行一個整數表示答案。

Sample Input 2 10 2 50 10 2 100

Sample Output 9 5 解題思路:簽到題,每次至少投入m快錢,每次系統拿掉p%也就是說每次會減少m*p%的錢,用一個迴圈,每次模擬,當剩下的錢不夠m的時候退出就行 AC程式碼:
#include<cstdio>
int
main(void) { int t,n,m,p; scanf("%d",&t); while(t--) { scanf("%d%d%d",&n,&m,&p); int sum=0; while(n>=m)//判斷條件 { n-=(m*p/100.0);//每次減少的錢 sum++; } printf("%d\n",sum); } return 0; }

Distance

Time Limit: 2000/1000 MS (Java/Others)Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 65Accepted Submission(s): 21

傳送門
Problem Description 小沃沃所在的世界是一個二維平面。他有n個朋友,第i個朋友距離他的距離為a[i],小沃沃並不知道這些朋友具體在什麼點上。

請問在最優情況下,小沃沃的朋友兩兩之間的歐幾里得距離的和的最小值是幾?

假設小沃沃的位置為P0=(x0,y0),第i個朋友的位置為Pi=(xi,yi),對於所有的i,需要滿足dist(P0,Pi)=a[i],並且n1i=1nj=i+1dist(Pi,Pj)最小,其中dist(X,Y)為連線點X和點Y的線段的長度。xi,yi都可以是任意實數。

Input 第一行一個正整數test(1test10)表示資料組數。

對於每組資料,第一行一個正整數n(1n100000)

接下來一行n個整數,第i個整數a[i](1a[i]1000000000)表示第i個朋友和小沃沃的距離。

Output 對每組資料輸出一行一個數,表示n1i=1nj=i+1dist(Pi,Pj)的最小值。答案需要四捨五入到整數。
Sample Input 2 2 3 5 5 1 2 3 4 5
Sample Output 2 20

解題思路:不要被題目的表面迷惑了,什麼xi,yi對題目沒有任何影響,我們只知道小沃沃的朋友距離小沃沃的長度,什麼時候他的朋友們的相互距離之和最小呢,我們都知道直線有最短距離

那麼他的朋友就是站成一條直線的。我們會想到用一個兩層迴圈去做,有些人就存在僥倖心理,莽一發O(n^2)直接交上去,然後秒T,沒錯就是我,,。

T掉之後,我們就會想優化,其實很容易發現當朋友們連成一條直線的時候,對朋友們的距離進行排序,就能得到有序的陣列,然後我們發現在計算的時候會有重複的部分,然後我們減去重複的部分就好了啊。

設K為第一個到其他的總和,那麼k0=10,然後每次減去(n-i)*b[i],不斷讓k更新。

AC程式碼:

#include<cstdio>
#include<algorithm>
using namespace std;
#define maxn 100005
#define ll long long
bool cmp(ll a,ll b)
{
    return a<b;
}
ll a[maxn],b[maxn];
int main(void)
{
    ll t,n;
    scanf("%lld",&t);
    while(t--)
    {
        scanf("%lld",&n);
        ll sum=0;
        for(ll i=0;i<n;++i)
        {
            scanf("%lld",&a[i]);
        }
        sort(a,a+n,cmp);
        ll k=0;//這個k表示的是第一個朋友到其他朋友的距離總和
        for(ll i=1;i<n;++i)
        {
            b[i]=a[i]-a[i-1];//求相鄰朋友的距離
            k+=(n-i)*b[i];
        }
        for(ll i=1;i<n;++i)
        {
            sum+=k;//每次加上每個朋友到其他朋友的距離(未被新增距離的朋友)
            k-=(n-i)*b[i];//更新k的值
        }
        printf("%lld\n",sum);
    }
    
}