2021BJTU新生賽預選賽題解


Problem A

  題意:二維平面中有一個地球E和一個二向箔V,V每次繞自己擴展一圈,求多少次后到達地球。

  題解:輸出E和V橫坐標差與縱坐標差中最大的即可。

  代碼:

 1 #include<bits/stdc++.h>
 2 #define int long long
 3 using namespace std;
 4 
 5 int T;
 6 int n, m;
 7 signed main() {
 8     int a, b, c, d;
 9     cin>>n>>m;
10     for(int i = 1;i<=n;++i) {
11         for(int j = 1; j<=m;++j){
12             char s;
13             cin>>s;
14             if(s == 'E') {
15                 a = i;
16                 b = j;
17             }
18             if( s== 'V') {
19                 c = i;
20                 d= j;
21             }
22         }
23     }
24     int l = abs(a-c);
25     int r = abs(b-d);
26     int ans = max(l,r);
27     cout<<ans;
28     return 0;
29 }

 

Problem B

  題意:儲藏倉初始位置為0,初始能量為0,每一點能量能使儲藏倉移動距離1。有n個核彈,第i個核彈在坐標為xi的位置,有vi的推動力。如果儲藏倉經過xi,那么該位置核彈會給儲藏倉增加vi點能量值。Q次詢問,每次詢問一個正整數k,詢問儲藏倉能否移動到坐標為k的位置。輸入保證xi遞增,第一個核彈在位置0。

  題解:記錄ans為當前能到達的最遠距離,輸入核彈的x和v時,若x<=ans,那么ans+=v。詢問時,判斷k是否小於等於ans即可。

  代碼:

 1 #include<bits/stdc++.h>
 2 #define int long long
 3 using namespace std;
 4 const int maxn = 1e5+1000;
 5 int T;
 6 int n, m;
 7 signed main() {
 8     cin>>n;
 9     int ans = 0;
10     for(int i = 1, p, v; i <= n; ++i) {
11         scanf("%lld%lld", &p, &v);
12         if(p<=ans) ans+=v;
13     }
14     cin>>m;
15     for(int i = 1; i <= m; ++i) {
16         int query;
17         scanf("%lld" ,&query);
18         if(query<= ans) printf("Yes\n");
19         else printf("No\n");
20     }
21     return 0;
22 }

 

Problem C

題意:兩群人分別有n個人和m個人。現有兩個智子,每個智子監控其中一群人,但一共只能監控p個人。求方案數。(對13331取模)

題解:用兩層循環,i、j,分別表示從第一群人中選i個人,第二群人中選j個人,要保證i+j小於等於p,然后用組合數求方案數。最后要減1,即減去選了0個人方案。組合數用遞推公式預處理即可。

 1 #include<bits/stdc++.h>
 2 #define int long long
 3 using namespace std;
 4 const int mod = 13331;
 5 int T;
 6 int n, m, p;
 7 int C[1010][1010];
 8 signed main() {
 9     cin>>n>>m>>p;
10     C[0][0] = 1;
11     for(int i = 1; i<= 1000;++i)
12         for(int j = 0;j<=1000;++j) 
13             if(j == 0) C[i][j] = 1;
14             else C[i][j] = C[i-1][j]+C[i-1][j-1]%mod;
15     int ans = 0;
16     for(int i = 0; i <= min(p,n); ++i) {
17         for(int j = 0; j<=min(p-i,m);++j) {
18             ans += C[n][i]*C[m][j]%mod;
19         }
20     }
21     ans--;
22     ans = (ans+mod)%mod;
23     cout<<ans;
24     return 0;
25 }

 

 

Problem D

題意:在Problem C的基礎上,有k(k <= 1e5)個智子來監控k群人,第i群人有ai個人(Σai <= 1e6)。一共只能監控p個人,求方案數。(對998244353取模)

題解:設總人數為sum。因為每個人都是獨立不重復的,那么答案就是C(sum, 1)+C(sum, 2)+C(sum, 3)+.....(It's just a joke)

代碼:

 1 #include<bits/stdc++.h>
 2 #define int long long
 3 using namespace std;
 4 const int mod = 998244353;
 5 const int maxn = 1e6+100;
 6 int T;
 7 int n, m, p, k, ans;
 8 int f[maxn], inv[maxn];
 9 int sum;
10 int ksm(int a, int b){
11     int ans = 1;
12     while(b) {
13         if(b&1) ans=(ans*a)%mod;
14         a =  a * a%mod;
15         b>>=1;
16     }
17     return ans;
18 }
19 int C(int sum,int to) {
20     f[0] = 1;
21     for(int i = 1 ;i<=sum;++i) f[i] = i*f[i-1]%mod;
22     inv[sum] = ksm(f[sum], mod-2);
23     for(int i = sum - 1; i >= 0; --i) inv[ i ] = inv[i+1] * (i + 1) % mod;
24     for(int i = 1;i<=to;++i) {
25         ans = (ans+f[sum]*inv[i]%mod*inv[sum-i])%mod;
26     }
27     return ans;
28 }
29 signed main() {
30     cin>>k;
31     for(int i = 1; i<=k;++i){
32         int a;
33         scanf("%lld", &a);
34         sum +=a;
35     }
36     cin>>p;
37     cout<<C(sum, min(sum, p));
38     return 0;
39 }

 

Problem E

題意:游戲贏一局得1分,輸一局得-1分。連贏三局時,贏一局得2分。贏一局得概率是a / b。k (k <= 1000)次詢問,每次詢問求 n (n <= 1e9)局后期望得分(對19260817取模)。

題解:找規律。設贏一局概率p。n = 1時,期望得分是2*p-1。n = 2時,期望得分是4*p-2。n = 3時,期望得分是p*p*p +6*p - 3。n = 4時,期望得分是2*p*p*p +8*p - 4。那么猜測答案是(n-2)*p*p*p +n(2p - 1)。打表發現確實是這樣(我這個憨憨最開始式子推錯了,所以是嗯打表找出來的規律)。

代碼:

 1 #include<bits/stdc++.h>
 2 #define int long long
 3 using namespace std;
 4 const int mod = 19260817;
 5 int T;
 6 int ans;
 7 int n, a, b;
 8 int inv,win;
 9 int ksm(int a, int b){
10     int ans = 1;
11     while(b) {
12         if(b&1) ans=(ans*a)%mod;
13         a =  a * a%mod;
14         b>>=1;
15     }
16     return ans;
17 }
18 signed main() {
19     cin>>T;
20     while(T--) {
21         ans = 0;
22         scanf("%lld%lld%lld", &n, &a, &b);
23         inv = ksm(b, mod-2);
24         win = a * inv % mod;
25         if(n == 1) ans = (2 * win - 1)%mod;
26         else if(n == 2) ans = (4*win - 2)%mod;
27         else {
28             int base = (win*win%mod*win%mod)%mod;
29             ans = (base * (n-2))%mod;
30             ans = (ans+ n * (2*win - 1)%mod)%mod;
31         }
32         printf("%lld\n", ans);
33     }
34     return 0;
35 }

 

Problem F

題意:把一些數字的所有因數寫在紙上,每張紙寫一個因數,一共n (n <= 5000) 張紙。求出原來的那些數字。

題解:可以發現1的個數就是原來的數字的個數(雖然沒什么用)。把所有因數從大到小排序,每取一個數,暴力往下刪除它的所有因數。

代碼:

 1 #include<bits/stdc++.h>
 2 #define int long long
 3 using namespace std;
 4 
 5 int T;
 6 int n, m;
 7 int a[50500],ans[50050],vis[50050];
 8 int sum;
 9 int cnt;
10 signed main() {
11     cin>>n;
12     for(int i = 1; i<=n;++i) 
13         scanf("%lld", &a[i]);
14     sort(a+1, a+1+n);
15     int qwq = 0;
16     for(int i = n; i>=1; --i){
17         if(!vis[i]){
18             int last = 0;
19             ans[++qwq] = a[i];
20             for(int j = 1; j < i; ++j){
21                 if(a[j]!=last && !vis[j] && a[i]%a[j] == 0&& a[i]!=a[j]){
22                     last = a[j];
23                     vis[j] = 1;
24                 }
25             }
26         }
27     }
28     sort(ans+1, ans+1+qwq);
29     cout<<qwq<<endl;
30     for(int i = 1; i <= qwq; ++i)
31         printf("%lld ", ans[i]);
32     return 0;
33 }


免責聲明!

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



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