1. 程式人生 > >牛客小白月賽5 : A D F G H I J

牛客小白月賽5 : A D F G H I J

比賽感想:

77名並不是很理想,本可以更好,況且大佬們都沒打這種比賽。

這裡寫圖片描述
前面五個題目 A G H I J ,基本上是1A,只有 I 題陣列全部開了long long 爆了一次記憶體
當時排名20+
後面開始做D,一看題目就知道結果是5的個數
但是,一個這麼簡單的題,讓我寫錯了,讓我寫錯了,讓我寫錯了
而且我當時還懷疑資料有問題,犯了不應該的錯誤,以此為戒
主要錯誤出自於下面的kaven函式:計算n中含有多少個因數5, 比如25是2個因數5 ,30是1個因數5
下面的程式碼有明顯錯誤,我卻不進行測試,還吐槽資料有問題(真是有病!)
貼出我錯誤的sb程式碼:

int
kaven(int n){ int sum=1; for(int i=1;;i++){ sum*=5; if(sum==n) return i; else if(sum>n) return i-1; } }

D題打亂了我的節奏後,以至於後面做 F 題的時候沒有安心推規律,導致F題也沒過掉
以至於後面一個多小時沒有過題。

下面是這次比賽較容易的七個題 A D F G H I J

A 無關(relationship)
經典容斥原理題目。

#include<bits/stdc++.h>
using
namespace std; typedef long long ll; const int maxn=25; int k; ll ans[maxn]; ll kaven(ll a){ if(a==0) return 0; ll num=a; for(int i=1;i<(1<<k);i++){ int cnt=0; ll mul=1; bool isok=true; for(int j=0;j<k;j++){ if(i&(1<<j)){ cnt++; if
(a/mul<ans[j]){ isok=false; break; } mul*=ans[j]; } } if(isok){ if(cnt%2) num-=a/mul; else num+=a/mul; } } return num; } int main(){ ll l,r; scanf("%lld%lld%d",&l,&r,&k); for(int i=0;i<k;i++) scanf("%lld",&ans[i]); printf("%lld\n",kaven(r)-kaven(l-1)); }

D 階乘(factorial)
結果就是有多少個5
這就很簡單了

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;

inline int kaven(int n,int mul){

    int cnt=0;
    while(n%mul==0) cnt++,n/=mul;
    return cnt;
}

int main(){

    int n;
    scanf("%d",&n);
    ll a;
    a=0;
    for(int i=5;i<=n;i+=5){

        a+=(ll)(n-i+1)*kaven(i,5);
    }
    printf("%lld\n",a);
}

F 圓(circle)
下面圖片摘自題解
這裡寫圖片描述
上面題解結果計算有點問題
F=E-V+2=C(n,4)+n*(n-1)+2
因為圓外還有一個區域,要減掉,因為題目是求圓內的區域個數
所以答案是:C(n,4)+n*(n-1)+1

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;

int main(){

    ll n;
    while(scanf("%lld",&n)==1){

        printf("%lld\n",1+n*(n-1)/2+n*(n-1)*(n-2)*(n-3)/24);
    }
    return 0;
}

G 異或(xor)
開始題目意思沒看懂,我就去看樣例,發現魚為偶數條的時候不能吃
題目看不懂,就只能碰碰運氣了,看樣例猜結論了
這是一個斐波拉契數列
1 1 2 3 5 8 13 21 34
奇 奇 偶 奇 奇 偶 奇 奇 偶
天數是三的倍數時,魚的數量為偶數,即不能吃
所以有n -n/3 天能吃
交上去就A了,果然樣例出奇跡

#include<cstdio>
using namespace std;

int main(){

    long long n;
    while(scanf("%lld",&n)==1){

        printf("%lld\n",n-n/3);
    }
}

H 最大公約數(lcm)
水題

#include<bits/stdc++.h>
using namespace std;

typedef unsigned long long ll;

inline ll gcd(ll a,ll b){

    return b==0?a:gcd(b,a%b);
}

int main(){

    ll n,m;
    scanf("%llu%llu",&n,&m);
    printf("%llu",n/gcd(n,m)*m);
} 

I 區間 (interval)
經典樹狀陣列區間修改和區間查詢題,用線段樹的話,記憶體應該會爆吧,我用樹狀陣列把陣列全部開long long記憶體就爆了,後面把 ans[] 改成 int 才過,線段樹估計也懸

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
const int maxn=1000000+100;

ll bit[maxn][2];
int ans[maxn];

int n,m;

inline int lowbit(int x){

    return x&(-x);
}

inline void Add(int x,ll v,int ind){

    while(x<=n){

        bit[x][ind]+=v;
        x+=lowbit(x); 
    }
}

inline ll getSum(int x,int ind){

    ll sum=0;
    while(x>0){

        sum+=bit[x][ind];
        x-=lowbit(x);
    }
    return sum;
}

int main(){

    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){

        scanf("%lld",&ans[i]);
    }
    for(int i=1;i<=m;i++){

        int q,l,r,p;
        scanf("%d%d%d%d",&q,&l,&r,&p);
        if(q==1){

            p*=-1;
            Add(l,p,0);
            Add(r+1,-p,0);
            Add(l,(ll)l*p,1);
            Add(r+1,(ll)(-r-1)*p,1);
        }
        else{

            Add(l,p,0);
            Add(r+1,-p,0);
            Add(l,(ll)l*p,1);
            Add(r+1,(ll)(-r-1)*p,1);
        }
    }
    int l,r;
    scanf("%d%d",&l,&r);
    ll tmp=(r+1)*getSum(r,0)-getSum(r,1);
    tmp-=l*getSum(l-1,0)-getSum(l-1,1);
    for(int i=l;i<=r;i++) tmp+=(ll)ans[i];
    printf("%lld\n",tmp); 
} 

J 時間(time)
簡單題

#include<bits/stdc++.h>
using namespace std;


int main(){

    int a,b;
    scanf("%d:%d",&a,&b);
    if(a==0){

        int c,d;
        c=0,d=0;
        if(d<b) printf("%d:%d\n",c,d);
        else{

            printf("%d:%d\n",23,32);
        }
        printf("1:10");
    }
    else if(a==23){

        int c,d;
        c=23,d=32;
        if(d<b) printf("%d:%d\n",c,d);
        else{

            printf("22:22\n");
        }
        c=23,d=32;
        if(d>b) printf("%d:%d\n",c,d);
        else{

            printf("0:0\n");
        }
    }
    else{

        int c,d;
        c=a;
        d=c%10*10+c/10;
        if(d<b) printf("%d:%d\n",c,d);
        else{
            c--;
            d=c%10*10+c/10;
            while(d>=60) c--,d=c%10*10+c/10;
            printf("%d:%d\n",c,d);
        }
        c=a;
        d=c%10*10+c/10;
        if(d>b&&d<60) printf("%d:%d\n",c,d);
        else{
            c++;
            d=c%10*10+c/10;
            while(d>=60) c++,d=c%10*10+c/10;
            printf("%d:%d\n",c,d);
        }
    }
}