2018CCPC吉林賽區 | 部分題解 (HDU6555 HDU6556 HDU6559 HDU6561)


 // 杭電上的重現賽:http://acm.hdu.edu.cn/contests/contest_show.php?cid=867

 // 杭電6555~6566可交題

A - The Fool 

題目大意:

求∑(1,n) [n/i] 的奇偶性。

分析及代碼:

這個求和可以分塊計算,復雜度O(√N),完全可行。

我覺得是水題就打表找規律了,發現前3項1~3結果是奇數,接着5項4~8結果是偶數,再接着7項是奇數,再然后9項時偶數......如此交替。

那么只需要計算n在哪一段就能確定奇偶性了,時間復雜度O(1)。

 

AC代碼:

#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;

int main() {
    int t = 0, T; cin>>T;
    while(t<T) {
        int n;
        scanf("%d", &n);
        int k = sqrt(n+1);
        if(k*k<n+1) ++k;


        printf("Case %d: ", ++t);
        if(k&1) printf("even\n");
        else printf("odd\n");
    }

    return 0;
}
View Code

 

 

B - The World

題目大意:

 世界時間換算問題,本題只考慮4個城市,每次給兩個城市和其中一個城市的時間,求另一城市的時間。

分析及代碼:

聽說隊友A不掉,然后又看不懂樣例了,遂嘗試解題。

本題還是有點坑的,如果給定的時間都是標准24小時制,那就非常簡單了,加加減減就完事了。

看了百度百科才明白什么是真正的12小時制

十二小時制是一個時間規則把一日二十四小時分為兩個時段,分別為上午(拉丁文ante meridiem表示中午之前)和 下午(拉丁文post meridiem表示中午之后)。每個時段由十二個小時構成,以數字12、1、2、3、4、5、6、7、8、9、10、11依次序表示。

所以12小時制里是不存在 0:30 AM 和 0:30 PM 的!!!

 

注意24小時制與12小時的轉化后,就沒什么問題了O.O

#include<iostream>
#include<cstdio>
#include<cmath>
#include<string>
#include<map>
using namespace std;
map<string, int> mp;
int main() {

    mp["Beijing"] =  8;
    mp["Washington"] = -5;
    mp["London"] = 0;
    mp["Moscow"] = 3; 

    string city1, city2;
    int h, min;
    string ap;
    int t = 0, T; cin>>T;
    while(t<T) {
        scanf("%d:%d", &h, &min);
        cin>>ap;
        cin>>city1;
        cin>>city2;

        if(ap=="PM" && h!=12) h += 12;   // 轉化成24小時制
        if(ap=="AM" && h==12) h = 0;

        h += mp[city2] - mp[city1];
        printf("Case %d: ", ++t);

        if(h>=24) {
            printf("Tomorrow ");
            h -= 24;
        }else if(h<0) {
            printf("Yesterday ");
            h += 24;
        } else {
            printf("Today ");
        }

        if(h>=12) printf("%d:%02d PM\n", h==12?12:h-12, min);
        else 
            printf("%d:%02d AM\n", h==0?12:h, min);
        
        
    }

    return 0;
}
View Code

 

E - The Tower

題目大意:

 計算幾何題。給你一個高h,底面半徑r的圓錐體,以及一個點(x0, y0, z0)和速度(vx, vy, vz),求什么時候落到圓錐面上。

分析及代碼:

一看很簡單啊,求直線方程與圓錐面的交點就完事了。

整了半天把圓錐面的方程寫出來了(開始寫錯WA了一發):

  (z - h)^2 = h^2/r^2 * (x^2+y^2)

直線方程

  (x-x0)/vx = (y-y0)/vy = (z-z0)/vz

聯立消去x, y

解一元二次方程求出z

注意z的范圍0<=z<=h,篩選過后選距離z0近的一點,fabs((z-z0)/vz)就是答案。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
#define sqr(x) ((x)*(x))

int main() {
    double r, h;
    double x0, y0, z0, vx, vy, vz;
    int t = 0, T; cin>>T;
    while(t<T) {

        scanf("%lf %lf", &r, &h);
        scanf("%lf %lf %lf", &x0, &y0, &z0);
        scanf("%lf %lf %lf", &vx, &vy, &vz);
        printf("Case %d: ", ++t);

        if(fabs(vz)<1e-8) { // 一定要特殊處理,后面的計算vz作了分母
            if(fabs(vy)<1e-8) {
                double xx = sqr((z0-h)*(r/h)) - y0*y0;
                xx = sqrt(xx);
                printf("%.10lf\n", min(fabs(xx-x0), fabs(-xx-x0))/fabs(vx));
            } else {
                double a = 1 + sqr(vx/vy);
                double b =2*vx/vy*(x0-vx/vy*y0);
                double c = sqr(x0-vx/vy*y0) - sqr(r/h)*sqr(z0-h);

                double y1 = (-b+sqrt(b*b-4*a*c))/2/a;
                double y2 = (-b-sqrt(b*b-4*a*c))/2/a;
                printf("%.10lf\n",  min(fabs(y1-y0), fabs(y2-y0))/fabs(vy));
            }
            continue;
        }
        double a = (vx*vx+vy*vy)/(vz*vz) - r*r/(h*h);
        double b = 2*(vx/vz*(x0-vx/vz*z0)+vy/vz*(y0-vy/vz*z0)) + 2*r*r/h;
        double c = sqr(x0-vx/vz*z0) + sqr(y0-vy/vz*z0) - r*r;
    //    printf("%lf %lf %lf\n", a, b, c);
        
        if(fabs(a)<1e-8) { // 實際沒用,可以刪掉
            printf("%.10lf\n", fabs((-c/b-z0)/vz));
            continue;
        }
        double z1 = (-b+sqrt(b*b-4*a*c))/2/a;
        double z2 = (-b-sqrt(b*b-4*a*c))/2/a;

    //    double zz = fabs(z1-z0)<fabs(z2-z0)?z1:z2;
    //    double xx = x0 + vx/vz*(zz-z0);
    //    double yy = y0 + vy/vz*(zz-z0);
        double zz;
        if(z1>h) zz = z2;
        else if(z2>h) zz = z1;
        else zz = fabs(z1-z0)<fabs(z2-z0)?z1:z2;
        
        printf("%.10lf\n", fabs((zz-z0)/vz));

    }
    
    return 0;
}
View Code

 

PS: 看到題解令(x-x0)/vx = (y-y0)/vy = (z-z0)/vz = t, 用t分別表示x, y, z再帶入圓錐方程,直接解出t,貌似可以不用特殊處理(vz=0的情況)。

 

 

G - High Priestess

題目大意:

 給你數量10^4個阻值為1歐的電阻,求通過串並聯得到一個阻值為r的等效電阻的方案,精度至少為1e-8。

分析及代碼:

將阻值r轉化為連分數的形式,然后根據串並聯公式將分式里的+合理轉化成相應形式。

具體來說,連分數的數位ki有奇數個的時候:

  1. 最后一個數字先並聯(如1/3就是三個1歐並聯);
  2. 將接下來的數字串聯,並且接着與前一個電路串聯
  3. 再將接下來的數字並聯,並且接着與前一個電路並聯
  4. 交替進行2-3兩步,直到數位枚舉完畢。

連分數的數位為偶數時,跟上面過程相似,不同的是第一步為串聯,以后步驟的串聯與並聯交換即可。

例如組成 r = 0.33 = 1/(3 + 1/33)

  1. 33個1歐電阻串聯得到33歐
  2. 3個1歐並聯得到1/3歐,1/3與33並聯得到 33/100,即0.33。
  3. 兩個數字枚舉完,結束。

 

代碼WA了,還在debug...

 


 

 

(未完待續。。。)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM