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 }