東北林業大學第15屆校賽(大一組)+雜題+訓練一

RealKing_ph發表於2020-12-22

東北林業大學第15屆校賽(大一組)+雜題+訓練一

來源

A-三角形面積

#include<bits/stdc++.h>
#define ll long long
#define MAX_N 1e+9
#define MAX_L 1e+18
using namespace std;

int main(){
    double a,b,c;
    cin>>a>>b>>c;
    double p=(a+b+c)/2;
    double ans;
    ans=sqrt(p*(p-a)*(p-b)*(p-c));
    printf("%.1lf",ans);
    return 0;
}

B-最大質因子

#include<bits/stdc++.h>
#define ll long long
#define MAX_N 1e+9
#define MAX_L 1e+18
using namespace std;

int main(){
    ll n;
    ll a;
    cin>>n;
    for(ll i=2;i<n/i;i++)
    {
        if(n%i==0)
        {
            while(n%i==0)
                n/=i;
                a=i;
        }
    }
    if(n>1) cout<<n;
    else    cout<<a;
    return 0;
}

C-楊輝三角

資料比較小,可以有兩種寫法。

  1. 缺點,資料越大,陣列就要開的越大,可能遇到開不了的情況。但,最大 n=31的時候long long爆掉,空間大小可以忽略。
#include<bits/stdc++.h>
#define ll long long
#define MAX_N 1e+9
#define MAX_L 1e+18
using namespace std;

int main(){
    ll a[31][31];
    a[1][1]=1;
    int n;cin>>n;
    for (int i=1;i<=n;i++){
    a[i][1]=1;
    a[i][i]=1;
        for(int j=2;j<=i-1;j++)
        {
            a[i][j]=a[i-1][j]+a[i-1][j-1];
        }
    }
    for (int i=1;i<=n;i++){
    for (int j=1;j<=i;j++){
        cout<<a[i][j]<<" ";
        }
        cout<<endl;
    }
    return 0;
}
  1. 缺點,每個資料輸出都要算一遍。但,最大 n=31的時候long long爆掉,時間可以忽略。推薦這種寫法,這是用組合數來寫的,此函式同樣可以運用到別的題目中。
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;

ll Cnm(ll n,ll m){
    if(m==0||m==n)    return 1;
    ll ans=1;
    ll p,q;
    if(m>n-m)   p=m,q=n-m;
    else        p=n-m,q=m;
    for(ll i=p+1;i<=n;i++)  ans*=i;
    for(ll i=1;i<=q;i++)    ans/=i;
    return ans;
}
int main(){
    int n;cin>>n;
    cout<<"1"<<" "<<endl;
    for(ll i=1;i<=n-1;i++){
        for(ll j=0;j<=i;j++){
            cout<<Cnm(i,j)<<" ";
        }
        cout<<endl;
    }
    return 0;
}

D-NEFU的數目

暴力搜尋就可以了。

#include<bits/stdc++.h>
#define ll long long
#define MAX_N 1e+9
#define MAX_L 1e+18
using namespace std;

int main(){
    char a[55];
    cin>>a;
    int len=strlen(a);
    int count=0;//答案
    for(int b=0;b<len;b++)
    {
        if(a[b]=='n')
        {
            for(int c=b+1;c<len;c++)
            {
                if(a[c]=='e')
                {
                    for(int d=c+1;d<len;d++)
                    {
                        if(a[d]=='f')
                        {
                            for(int e=d+1;e<len;e++)
                            {
                                if(a[e]=='u')
                                {
                                    count++;
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    cout<<count;
    return 0;
}

E-最少修改次數(1)

滑動視窗,最最簡單基本的一種,請上百度搜尋,學習一下整塊的知識。

#include<bits/stdc++.h>
#define ll long long
#define MAX_N 1e+9
#define MAX_L 1e+18
using namespace std;

int main(){
    char a[1003],b[1003];
    cin>>a>>b;
    int len1=strlen(a);
    int len2=strlen(b);
    int count=0;
    if(len1==len2){
        for(int i=0;i<len1;i++){
            if(a[i]!=b[i])  count++;
        }
    }
    else{//動態視窗!!!
        count=10000;
        for(int i=0;i<=len1-len2;i++)
        {
            int k=0;
            for(int j=0;j<len2;j++)
            {
                if(a[j+i]!=b[j])
                    k++;
            }
            count=min(k,count);
        }
        //if(count=10000) count=0;
    }
    cout<<count;
    return 0;
}

F-字典序

有兩種做法

  1. 按照常理,只要判斷最後一位就可以辣。

    #include<bits/stdc++.h>
    #define ll long long
    #define MAX_N 1e+9
    #define MAX_L 1e+18
    using namespace std;
    
    int main(){
        int n;
        cin>>n;
        int a;
        if(n/32767) 	//
            cout<<"77777";
        else
        {
            if(n/32760) {a=7777*10+n%32760;cout<<a;}//8^5-8~8^5-1以下同理
            else if(n/4095) cout<<"7777";
            else
            {
                if(n/4088){a=777*10+n%4088;cout<<a;}
                else if(n/511)  cout<<"777";
                else
                {
                    if(n/504){a=77*10+n%504;cout<<a;}
                    else if(n/63)   cout<<"77";
                    else
                    {
                        if(n/56){a=7*10+n%56;cout<<a;}
                        else if(n/7)cout<<"7";
                        else
                        {
                            cout<<n;
                        }
                    }
                }
            }
        }
    }
    
  2. 用string自動來比較。::看周思樂的題解。

G-最小差值

比較水。

    #include<bits/stdc++.h>
    #define ll long long
    #define MAX_N 1e+9
    #define MAX_L 1e+18
    using namespace std;
    ll a[200006];
    int main(){
        int n;
        cin>>n;
        for(int i=0;i<n;i++)
        cin>>a[i];
        ll sum1,sum2;
        sum1=sum2=0;
        for(int i=0;i<n;i++)
        sum2+=a[i];
        ll minn=100000000;
        ll k;
        for(int i=0;i<n;i++)
        {
            k=abs(sum2-sum1);
            minn=min(minn,k);
            sum1+=a[i];
            sum2-=a[i];
        }
        minn=min(minn,k);
        cout<<minn;
    }

H-染色方案

  1. 二進位制暴力列舉就好。
#include<stdio.h>
int main(){
    int n,m,k;
    scanf("%d%d%d",&n,&m,&k);
    int a[7][7];
    for(int i=0;i<n;i++){
        for(int j=0;j<m;j++){
            scanf("%d",&a[i][j]);
        }
    }
    int ans=0,count;
    for(int i=0;i<(1<<n);i++){
        for(int j=0;j<(1<<m);j++){
            count=0;
            for(int p=0;p<n;p++){
                for(int q=0;q<m;q++){
                    if(((1<<p)&i)&&((1<<q)&j))
                        count+=a[p][q];
                }
            }
            if(count==k)    ans+=1;
        }
    }
    printf("%d\n",ans);
}
  1. 也可以用深度搜尋解決掉,相對於上一種方法,這種方法程式碼量有點大,故不貼了。

I-最大正方形

排序就可。

    #include<bits/stdc++.h>
    #define ll long long
    #define MAX_N 1e+9
    #define MAX_L 1e+18
    using namespace std;
    bool cmp(int a,int b)
    {
        return a<=b;
    }
    int main ()
    {
        int a[1003];
        int n;cin>>n;
        for(int i=0;i<n;i++)
            cin>>a[i];
        sort(a,a+n,cmp);//可以學一學sort()函式的使用,在<algorithm>標頭檔案裡。
        				//資料量比較小,用qsort()還是冒泡啥的都沒有問題。
        int k;
        for(int i=1;i<=n;i++)
        {
            k=0;
            for(int j=n-1;j>=0;j--)
            {
                if(a[j]>=i) k++;
            }
            if(k>=i) continue;
            else
            {
                k=i-1;
                break;
            }
        }
        cout<<k;
    }

J-最大值

    #include<bits/stdc++.h>
    #define ll long long
    #define MAX_N 1e+9
    #define MAX_L 1e+18
    using namespace std;
    int a[200006];
    int main(){
        int n;cin>>n;
        for (int i=0;i<n;i++)
            cin>>a[i];
        int maxxx=0;
        for(int i=0;i<n;i++)
            maxxx=max(maxxx,a[i]);
        int p=0;
        int k;//標記出位置
        for(int i=0;i<n;i++)
        {
            if(maxxx==a[i])
            {
               p++;
               k=i;
            }
        }
        if(p==1)
        {
            int maxxxx=0;
            for(int i=0;i<n;i++)
            {
                if(i==k)    continue;
                maxxxx=max(maxxxx,a[i]);
            }
            for(int i=0;i<n;i++)
            {
                if(i==k)
                {
                    cout<<maxxxx<<'\n';
                    continue;
                }
                cout<<maxxx<<'\n';
            }
        }
        else
        {
            for(int i=0;i<n;i++)
            cout<<maxxx<<'\n';
        }
    }

K-迴圈排列

當時沒學map沒學結構體這些,導致程式碼比較臃腫,不夠簡潔不夠美觀。

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<cstdlib>
    #define ll long long
    using namespace std;
    int a[200005];
    int b[200005];
    int c[200005];
    int d[200005];
    int e[200005];
    int main (){
        int n;cin>>n;
        for(int i=1;i<=n;i++)
            cin>>a[i];
        for(int i=1;i<=n;i++)
            cin>>b[i];
        for(int i=1;i<=n;i++){
            c[a[i]]=i;
            d[b[i]]=i;
        }
        for(int i=0;i<=n;i++)
            e[i]=0;
        int f;
        for(int i=1;i<=n;i++){
            f=c[i]-d[i];
            if(f<0) f+=n;
            e[f]++;
        }
        int maxx=0;
        for(int i=0;i<=n;i++){
            maxx=max(maxx,e[i]);
        }
        cout<<maxx;
    //    system("pause");
    }
//更簡潔看sl妹妹的題解。

L-庫特與圍棋

氣只出現在四方,即上下左右,也就是說,我們越要氣小也就越要堵住四方的棋子。也就是正方形。

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cstdlib>
    #include <cmath>
    #include <ctime>
    #define MAX_N 1e+9
    #define MAX_X 1e+18
    #define ll long long
    using namespace std;
    int main()
    {
        ll a;cin>>a;
        ll b=sqrt(a);
        ll ans=4*b;
        ll c=a-b*b;
        if(c==0)            cout<<ans<<endl;
        else if(c>0&&c<=b)  cout<<ans+2<<endl;
        else if(c>b)        cout<<ans+4<<endl;
    }

一些附加的題目

14校賽-K-庫特的鴿鴿們

主要就是存下特定的鴿子的最後一次運算元。

該題目只需要注意一下時間複雜度就可以了。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<ctime>
#include<cmath>
#define MAX_N 1e+9
#define MAX_X 1e+18
#define LL long long
using namespace std;

int a[200005];
int x[200005];
int y[200005];
int maxx[200005];//從後往前二號最大運算元
int z[200005];//存下對應的運算元

int main (void){
    int n;cin>>n;
    for(int i=1;i<=n;i++)
        cin>>a[i];
    //存入x y;
    int q;cin>>q;
    for(int i=1;i<=q;i++){
        cin>>x[i];
        y[i]=-1;
        if(x[i]==1)     cin>>x[i]>>y[i];
        else if(x[i]==2)cin>>x[i];
    }
    //從後往前,操作二的最大一次操作。
    if(y[q]>=0)     maxx[q]=0;
    else            maxx[q]=x[q];
    for(int i=q-1;i>0;i--){
        if(y[i]<0)  maxx[i]=max(x[i],maxx[i+1]);
        else        maxx[i]=maxx[i+1];
    }
    //將最後一次一號操作的數儲存下來
    for(int i=q;i>0;i--){
        if(y[i]<0)  continue;
        else{
            if(a[x[i]]>=0){
                a[x[i]]=-1;//標記處被改變的那個量
                z[x[i]]=i;//儲存運算元;
            }
        }
    }

    for(int i=1;i<=n;i++){
        if(q==0){
            cout<<a[i]<<" ";
        }
        
        else{
            if(a[i]<0){
                cout<<max(y[z[i]],maxx[z[i]])<<" ";
            }
            else{
                cout<<max(a[i],maxx[1])<<" ";
            }
        }
    }
//    system("pause");
}

Take apples

解決這個問題的關鍵點在於,A可以保證每次取完之後,在第r輪共可以取r+1個蘋果。

該知識需要學習博弈論。博主還沒有開始學習,以後會再補充。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<ctime>

using namespace std;

int main (){
    int t;
    cin>>t;
    while (t--){
        int n;
        cin>>n;
        n=(n+1)*2;
        int n1=sqrt(n);
        if ((n1)*(n1+1)==n){
            cout<<"YES"<<endl;
        }
        else{
            cout<<"NO"<<endl;
        }
    }
    return 0;
}

Values whose Sum is 0

兩種做法

  1. 兩端縮小

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<cstdlib>
    #define ll long long
    using namespace std;
    const int maxn=4001;
    ll a[maxn],b[maxn],c[maxn],d[maxn];
    ll e[maxn*maxn],f[maxn*maxn];
    ll n;
    bool binarysearch(ll x){
        ll l=0,r=n*n-1;
        ll mid;
        while(r>=l){
            mid=(l+r)/2;
            if(f[mid]==x)       return true;
            else if(f[mid]>x)   r=mid-1;
            else                l=mid+1;
        }
        return false;
    }
    
    int main(){
        int t;cin>>t;
        int first=0;
        while(t--){
            if(first){
                puts("");
            }else{
                first=1;
            }
            cin>>n;
            for(ll i=0;i<n;i++){
                cin>>a[i]>>b[i]>>c[i]>>d[i];
            }
            ll k=0;
            for(ll i=0;i<n;i++){
                for(int j=0;j<n;j++){
                    e[k]=a[i]+b[j];
                    f[k++]=c[i]+d[j];
                }
            }
            sort(e,e+n*n);
            sort(f,f+n*n);
            ll count=0;
            ll s;//控制第二層迴圈只走了一次。
            s=n*n-1;
            for(ll i=0;i<n*n;i++){
                for(ll j=s;j>=0;j--){//s為從什麼地方開始。
                    //測試
                    if(e[i]+f[j]>0)         s--;
                    else if(e[i]+f[j]==0)   count++;
                    else                    break;
                }
            }
            cout<<count<<endl;
        }
    }
    
  2. map對映

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=4005;
    int A[maxn], B[maxn], C[maxn], D[maxn], sumAB[maxn];
    int main() {
        int T, n;
        scanf("%d", &T);
        for (int k=0; k < T; k ++) {
            if (k != 0) puts("");
            scanf("%d", &n);
            for (int i=0; i < n; i ++) scanf("%d %d %d %d", &A[i], &B[i], &C[i], &D[i]);
            unordered_map<int, int> mp;
            for (int i=0; i < n; i ++) // A+B
                for (int j=0; j < n; j ++) mp[A[i]+B[j]] ++; // 計算每個和出現次數
            int ans=0;
            for (int i=0; i < n; i ++) // C+D
                for (int j=0; j < n; j ++) ans += mp[-(C[i]+D[j])];
            printf("%d\n", ans);
        }
        return 0;
    }
    

寒假訓練一嘉文部落格未寫出內容

前六題

後兩題

吐槽一句,基本每題都要多組輸入!!錯交了巨巨巨巨多次。

I-優秀學生

#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;

struct{
    string num,nam;
    int chenj;
} stuss[105];
int main(){
    int n;
    while(cin>>n){
        int a[101];int k=0;
        for(int i=0;i<n;i++){
            cin>>stuss[i].num>>stuss[i].nam>>stuss[i].chenj;
            if(stuss[i].chenj>=90)  a[k++]=i;
        }
        for(int i=0;i<k;i++){
            cout<<stuss[a[i]].num<<" "<<stuss[a[i]].nam<<" "<<stuss[a[i]].chenj<<endl;
        }
        cout<<k<<endl;
    }
}

J-誰不及格?

#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;

struct{
    string num,nam;
    double chenj;
} stuss[105];
int main(){
    int n;
    while(cin>>n){
        int a[101];int k=0;
        for(int i=0;i<n;i++){
            getchar();
            getline(cin,stuss[i].nam);
            cin>>stuss[i].num>>stuss[i].chenj;
            if(stuss[i].chenj<60)  a[k++]=i;
        }
        if(k==0)    cout<<"They are Great!!"<<endl;
        else{
            cout<<k<<endl;
            for(int i=0;i<k;i++){
                cout<<stuss[a[i]].nam<<endl;
            }
            for(int i=0;i<k;i++)cout<<stuss[a[i]].num<<endl;
            for(int i=0;i<k;i++)printf("%.2lf\n",stuss[a[i]].chenj);
        }
    }
}

因為題目都比較水,所以不做詳細的描述。

有問題請尋找sl妹妹~~。

最後,歡迎大家訪問我的github呀。

相關文章