https://ac.nowcoder.com/acm/contest/9536
20年11月27日的比賽了,一共20題,當時寫了十七題rank30,現在拿出來把它寫完整理一下吧。
A找一下規律。前三行:第i行輸出i-1個空格和V和2*(n-i)-1個空格和V和換行,最後一行輸出3個空格和一個V,循環搞定。
#include<bits/stdc++.h> using namespace std; int main() { int n=4; for(int i=1;i<n;i++) { for(int j=1;j<i;j++)cout<<' '; cout<<'V'; for(int j=1;j<=1+2*(n-i-1);j++) cout<<' '; cout<<'V'; cout<<endl; } for(int j=1;j<=n-1;j++) cout<<' '; cout<<'V'; return 0; }
B就讀入ab,輸出100*b/a的三位小數+百分號,用printf的保留三位小數挺好。(還好不想yyh的那道毒瘤題)
#include<bits/stdc++.h> using namespace std; int main() { long long a,b; cin>>a>>b; double x=100.00*b/a; printf("%.3f%%",x); return 0; }
C就讀入mn,如過m%n==0輸出YES,否則輸出NO。
#include<bits/stdc++.h> using namespace std; long long m,n; int main() { cin>>m>>n; if(m%n==0) cout<<"YES"; else cout<<"NO"; return 0; }
D題可以看做是一道60進制的減法。我就直接sum=(h2-h1)*60+m2-m1得到總的分鐘數,那麼小時應該是sum/60,分鐘數應該是sum%60。想一秒特殊情況:不到一小時和整小時,都挺對的,那就沒啥問題了。
#include<bits/stdc++.h> using namespace std; int a,b,c,d; int main() { cin>>a>>b>>c>>d; int sum=d-b+(c-a)*60; cout<<sum/60<<' '<<sum%60; return 0; }
E也是小模擬。本來還想開數組啥的,看一眼數據範圍是11~99僅有兩位數,if表達式挺好寫的,直接開搞。a==b時100塊;20塊是12、21這樣個位對應十位,十位對應個位這樣,a/10==b%10&&a%10==b/10;2塊是有一個數字相同,a%10==b/10||a%10==b%10||a/10==b/10||a/10==b%10。上面的用if和else if,0塊用else即可對應全部情況。
#include<bits/stdc++.h> using namespace std; int a,b; int main() { cin>>a>>b; if(a==b) cout<<100; else if(a%10==b/10&&a/10==b%10) cout<<20; else if(a%10==b/10||a%10==b%10||a/10==b/10||a/10==b%10) cout<<2; else cout<<0; return 0; }
F不想說了。
#include<bits/stdc++.h> using namespace std; int main() { int n; for(cin>>n;n;n--) cout<<"China will win the battle against COVID-19."<<endl; return 0; }
G可以sort得到最高最低分,但是平均分還是要掃一遍,那順便更新最高分最低分算了,不用sort了。
#include<bits/stdc++.h> using namespace std; int a[10010],maxx,minn,sum; int main() { int n; cin>>n; for(int i=1;i<=n;i++) cin>>a[i]; maxx=minn=a[1]; for(int i=1;i<=n;i++) { maxx=max(maxx,a[i]); minn=min(minn,a[i]); sum+=a[i]; } printf("%.2f %d %d",sum*1.0/n,maxx,minn); return 0; }
H到這兒我想起來了,我是先做的H再做的A,於是可以照搬代碼到A。那些先寫A的還要推一下公式哈哈哈哈。
#include<bits/stdc++.h> using namespace std; int main() { int n;cin>>n; for(int i=1;i<n;i++) { for(int j=1;j<i;j++)cout<<' '; cout<<'V'; for(int j=1;j<=1+2*(n-i-1);j++) cout<<' '; cout<<'V'<<endl; } for(int j=1;j<=n-1;j++) cout<<' '; cout<<'V'; return 0; }
I用map和數組寫都挺好。map寫完還要用迭代器,那個我沒學會,還是算了。這波啊,這波是空間換時間,如果空間開不下要用nlog(n)sort後掃一遍,寫起來也簡單。
#include<bits/stdc++.h> using namespace std; int t,sum[10010]; int main() { int n; cin>>n; for(int i=1;i<=n;i++) { cin>>t; sum[t]++; } for(int i=10000;i;i--) if(sum[i]) cout<<i<<'-'<<sum[i]<<endl; return 0; }
之前的題都是有手就行,下面的題需要一些能力了。
J是前綴和例題。令sum[i]=Σa[1],a[i],那麼p和q覆蓋的子序列和爲sum[q]-sum[p-1],預處理前綴和數組只需sum[i]=sum[i-1]+a[i],由於q可能大於n,於是把sum[n+1]到sum[10000]都賦值爲sum[n]。
#include<bits/stdc++.h> using namespace std; int a[1010],sum[10010]; int n,t,l,r; int main() { cin>>n; for(int i=1;i<=n;i++) cin>>a[i],sum[i]=sum[i-1]+a[i]; for(int i=n+1;i<=10000;i++) sum[i]=sum[i-1]; for(cin>>t;t;t--) { cin>>l>>r; cout<<sum[r]-sum[l-1]<<endl; } return 0; }
K是數論題。能同時被n和m整除的最小值是lcm(n,m),所有能同時被n和m整除的值是lcm(n,m)的整數倍。如果k>=lcm,把k減去k%lcm就是小於等於k的最大lcm的倍數,即爲所求;如果k<lcm,那麼不存在答案。
#include<bits/stdc++.h> using namespace std; long long gcd(long long a,long long b) { return b==0?a:gcd(b,a%b); } int main() { long long n,m,k; cin>>m>>n>>k; long long lcm=m/gcd(m,n)*n; if(k<lcm) cout<<-1; else cout<<k-k%lcm; return 0; }
L是一道高中數學題。問單詞學錯的種類,考慮求出所有的字母排列的方案數後-1即可。所有字母的排列方案是單詞長度的階乘/每個字母出現的次數的階乘,很好寫。
#include<bits/stdc++.h> using namespace std; int sum[300]; string s; int fac(int x) { int ans=1; while(x) ans=ans*x,x--; return ans; } int main() { cin>>s; for(int i=0;i<s.size();i++) sum[s[i]]++; int ans=fac(s.size()); for(int i='A';i<='Z';i++) ans=ans/fac(sum[i]); cout<<ans-1; return 0; }
M題要求數組元素的總和的方案數。注意到數組元素的總和的最小值是minn*(n-1)+maxx,最大值是maxx*(n-1)+minn,那麼答案就是最大值減最小值+1=maxx*n-minn*n-2*(maxx-minn)+1。
#include<bits/stdc++.h> using namespace std; long long n,minn,maxx; int main() { scanf("%lld%lld%lld",&n,&minn,&maxx); cout<<maxx*n-minn*n-2*(maxx-minn)+1; return 0; }
N問閉區間1到n有多少個因子個數爲3的數。首先1不是,大於1的數x至少有兩個因子1和x它自己。要想滿足因子個數是3,需要再來一個因子剛好是根號x。於是問題轉化成了求1到根號n中的質數的個數,這些質數的平方都是有趣的數。求質數需要根號n,那麼複雜度是根號n乘根號根號n=10^9,差不多能過。
#include<bits/stdc++.h> using namespace std; bool ask(long long x) { long long t=sqrt(x*1.0); for(int i=2;i<=t;i++) if(x%i==0) return 0; return 1; } int main() { int sum=0; long long n; cin>>n; for(long long i=2;i*i<=n;i++) if(ask(i)) sum++; cout<<sum; return 0; }
O題經典找不同。一般的題是給一個天平,用二分的方法。但是這道題直接給了一個能稱任意重量的電子秤,直接第i堆拿出i個稱重,本應是(1+n)*n/2g重,用實際的質量減它可以得到是那一堆硬幣重量爲2g,所以只需要分兩種情況:1和大於1,答案分別是0和1。
#include<bits/stdc++.h> using namespace std; int main() { long long n;cin>>n; cout<<(n==1?0:1); return 0; }
P給的N首先要能表示成2的正整數次冪的和,表明奇數必然不行了。考慮用lowbit得到N二進制裏的1的數量sum,然後不能直接拿着sum==3判斷答案,比如8,sum=1但是可以表示成4+2+2。這提醒我們大於等於8的數們即使sum=1也可以,這時N爲2^k,只需要拆分成N/2+N/4+N/4。大於6的數sum=2也可以,這時N=2^m+2^n,m>n,只需要拆分成2^(m-1)+2^(m-1)+2^n即可。sum=3當然可以了,sum>3的不行,不存在sum=0的正整數。
#include<bits/stdc++.h> using namespace std; int lowbit(int n) { return n&(-n); } int main() { int n,sum=0,t; cin>>n; if(n%2==1) { cout<<"NO"; return 0; } t=n; while(n) { n=n-lowbit(n); sum++; } if(t>=8&&sum==1||t>=6&&sum==2||sum==3) cout<<"YES"; else cout<<"NO"; return 0; }
Q題是個結論題:1/n是有限小數當且僅當n的質因子只有2和5。這是因爲1和任意有限小數除以2,5都是有限小數,除以其他質數都是無限小數。於是把輸入進來的n一直除以2和5,看看是不是剩下個1即可。