北华大学计算机程序设计算法提高训练营个人赛
A 洛姐打题日记
签到
#include<bits/stdc++.h>
using namespace std;
int32_t main() {
string s;
cin >> s;
if( s == "AC" )
cout << "Accepted\n";
else if( s == "WA")
cout << "Wrong Answer\n";
else if( s == "RE")
cout << "Runtime Error\n";
else if( s == "CE")
cout << "Compile Error\n";
else if( s == "TLE")
cout << "Time Limit Exceeded\n";
else if( s == "PE")
cout << "Presentation Error\n";
else if( s == "MLE")
cout << "Memory Limit Exceeded\n";
return 0;
}
B 鸡兔同笼
小学数学,解一下方程就好了
#include<bits/stdc++.h>
#define int long long
using namespace std;
int read() {
int x = 0, f = 1, ch = getchar();
while ((ch < '0' || ch > '9') && ch != '-') ch = getchar();
if (ch == '-') f = -1, ch = getchar();
while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
return x * f;
}
void solve()
{
int x = read() , y = read() , h = read(), f = read();
int a = ( f - h * y ) / ( x - y ) , b = h - a;
cout << a << " " << b << "\n";
}
int32_t main() {
int t = read();
while( t -- )
solve();
return 0;
}
C 小杜的签到
\[\sum_{i=1}^{n-1} ( a_{i+1} - a_i) = a_2-a_1+a_3-a_2+a_4-a_3+\cdots + a_n-a_{n-1}=a_n-a_1
\]
找一下最大值和最小值就好了
#include<bits/stdc++.h>
#define int long long
using namespace std;
int read() {
int x = 0, f = 1, ch = getchar();
while ((ch < '0' || ch > '9') && ch != '-') ch = getchar();
if (ch == '-') f = -1, ch = getchar();
while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
return x * f;
}
int32_t main() {
int n = read() , mx = -1e9 , mn = 1e9;
for( int x ; n ; n -- )
x = read() , mx = max( mx , x ) , mn = min( mn , x );
cout << mn - mx << " " << mx - mn << endl;
return 0;
}
D 我超!原!
据说正解是贪心,但是我用了枚举答案的方法。
首先计算计算一下升级到x
消耗的经验总和,然后特判一下特殊情况。我发现无论怎么组合,最终获得的经验总和一定是1000
的倍数。所以找到大于经验总和且是1000
倍数的最小值开始枚举,每次加1000
直到第一次找到答案输出就好
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int A = 20000ll , B = 5000ll , C = 1000ll;
int32_t main() {
int x , y , a , b , c , sum;
cin >> x >> y >> a >> b >> c;
if( x == 1 )
{
cout << "0\n";
return 0;
}
sum = ( x - 1 ) * 1000ll + y * ( x - 1ll ) * ( x - 2ll ) / 2ll;
if( a * A + b * B + c * C < sum ){
cout << "QAQ\n";
return 0;
}
for( int t = (sum / C + ( sum % C > 0 ) ) * C , i , j , k , p ; t ; t += C )
{
p = t;
i = min( a , p / A ) , p -= i * A;
j = min( b , p / B ) , p -= j * B;
if( c >= p / C ) {
cout << t - sum << endl;
return 0;
}
}
return 0;
}
E 佳乐的迷宫
因为终点只有一个,所以从终点开始dfs
找到所有的可以到达的点,然后判断哪些起点可以到达即可
#include<bits/stdc++.h>
using namespace std;
int read() {
int x = 0, f = 1, ch = getchar();
while ((ch < '0' || ch > '9') && ch != '-') ch = getchar();
if (ch == '-') f = -1, ch = getchar();
while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
return x * f;
}
const int dx[] = { 0 , 0 , 1 , -1 };
const int dy[] = { 1 , -1 , 0 , 0 };
const int N = 1005;
int n , m , k , cnt;
string st[N];
bitset<N> vis[N];
vector< int > res;
pair<int,int> ex[N*N];
void dfs( int x , int y ){
vis[x][y] = 1;
for( int i = 0 , fx , fy ; i < 4 ; i ++ )
{
fx = x + dx[i] , fy = y + dy[i];
if( fx < 0 || fy < 0 || fx >= n || fy >= m || st[fx][fy] == '#' || vis[fx][fy] ) continue;
dfs( fx ,fy );
}
}
int32_t main() {
n = read() , m = read() , k = read();
for( int i = 0 ; i < n ; i ++ )
cin >> st[i];
for( int i = 1 ; i <= k ; i ++ )
ex[i].first = read() - 1 , ex[i].second = read() - 1;
int x = read() , y = read();
dfs( x - 1 , y - 1 );
for( int i = 1 ; i <= k ; i ++ )
if( vis[ex[i].first][ex[i].second] ) res.push_back(i);
cout << res.size() << endl;
for( auto it : res )
cout << it << " ";
return 0;
}
F 三四五
虽然不懂博弈,但是比赛的时候我写了个递推,发现如果取的范围是[1,k]
那么k+1
的倍数一定是先手必败,然后轮数是n/(k-1)
次,找到最小的轮数判断谁胜就好了
#include<bits/stdc++.h>
using namespace std;
int read() {
int x = 0, f = 1, ch = getchar();
while ((ch < '0' || ch > '9') && ch != '-') ch = getchar();
if (ch == '-') f = -1, ch = getchar();
while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
return x * f;
}
int32_t main() {
int t = read();
for( int n , m , k , a , b , c ; t ; t -- ){
n = read() , m = read() , k = read();
a = n / 4 , b = m / 5 , c = k / 6;
if( a <= b && a <= c ){
if( n % 4 == 0 )
printf("(T-T)\n");
else printf("(^-^)\n");
}
else if( b <= c && b <= a )
{
if( m % 5 == 0 )
printf("(T-T)\n");
else printf("(^-^)\n");
}
else {
if( k % 6 == 0 )
printf("(T-T)\n");
else printf("(^-^)\n");
}
}
return 0;
}
G 杰哥的疑问
丢在 map 里面记一下数,然后枚举key就好了
#include<bits/stdc++.h>
#define int long long
using namespace std;
int read() {
int x = 0, f = 1, ch = getchar();
while ((ch < '0' || ch > '9') && ch != '-') ch = getchar();
if (ch == '-') f = -1, ch = getchar();
while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
return x * f;
}
map< int , int > st;
int32_t main() {
int n = read() , m = read() , cnt = 0;
for( int x ; n ;n -- )
x = read() , st[x] ++;
for( auto [ k , v ] : st ){
if( m - k < k ) break;
if( m - k == k ) {
cnt += v * ( v - 1 ) / 2;
break;
}
if( st.find( m - k ) == st.end() ) continue;
cnt += v * st[m-k];
}
cout << cnt << endl;
return 0;
}
H 墨染的斯汀木
先把整个s1
串转换成全部小写的字符串,然后根据s_0
判断一下就好
#include<bits/stdc++.h>
using namespace std;
string s , p , t;
int32_t main() {
cin >> s >> t;
for( auto it : t )
if( it >= 'A'&& it <= 'Z' ) p += it + 'a' - 'A' , p += it + 'a' - 'A';
else p += it;
for( int i = 0 , j = 0; i < s.size() ; i ++ , j ++ )
{
if( s[i] >= 'a' && s[i] <= 'z' )
cout << s[i];
else if( s[i] >= 'A' && s[i] <= 'Z' )
{
cout << s[i];
j ++;
}
else if( s[i] == '?' )
cout << p[j];
else
{
cout << char( p[j] + 'A' - 'a' );
j ++;
}
}
return 0;
}
I , J Darling
两道题我用了相同的方法过掉了。如果要保证最优的情况那么异性边的端点一定是起点,并且端点到异性的距离就是1
,然后从这些端点向外扩展,并且只扩展同性边,那么每次扩展到点到异性的距离就要加一。
对于这个过程的实现也非常的简单。首先读入边的时候只记录同性边,异性边的端点直接放到队列中,然后bfs
一下就好,复杂度O(N)
#include<bits/stdc++.h>
using namespace std;
int read() {
int x = 0, f = 1, ch = getchar();
while ((ch < '0' || ch > '9') && ch != '-') ch = getchar();
if (ch == '-') f = -1, ch = getchar();
while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
return x * f;
}
const int N = 1e6+5;
int n , m , t ;
int s[N] , vi[N] , dis[N];
vector<int> e[N] , nxt[2];
queue<int> q;
int32_t main() {
n = read(), m = read(), t = read();
for (int i = 1; i <= n; i++) s[i] = read();
for (int i = 1; i <= n; i++) dis[i] = -1;
for (int u, v; m; m--) {
u = read(), v = read();
if (s[u] != s[v])
dis[u] = dis[v] = 1, q.push(u), q.push(v);
else e[u].push_back(v), e[v].push_back(u); // 同性边
}
while (q.size()) {
int u = q.front();
q.pop();
for (auto v: e[u]) {
if (dis[v] != -1) continue;
dis[v] = dis[u] + 1, q.push(v);
}
}
for (int x; t; t--){
x = read();
printf("%d\n" , dis[x] );
}
return 0;
}
K 小杜返校记
这道题其实非常简单的,比赛的时候榜是歪的
#include<bits/stdc++.h>
using namespace std;
double n , t;
double p[5][5];
string a , b;
int32_t main() {
cin >> n >> t >> a >> b;
for( int i = 1 ; i <= 3 ; i ++ )
for( int j = 1 ; j <= 3 ; j ++ )
cin >> p[i][j];
int i , j;
if( a == "First" ) i = 1;
else if( a == "Business") i = 2;
else i = 3;
if( t >= 336 ) j = 0;
else if( t >= 48 ) j = 1;
else if( t >= 4 ) j = 2;
else j = 3;
printf("%.2lf\n" , n * ( 100 - p[i][j] ) / 100 );
return 0;
}