网址:Contest Problem List (hdu.edu.cn)
1001 | 签到题 | 对于文中的坑点,取模后不能为负数,导致迟迟未AC掉,签到题WA掉3次, 浪费了多次罚时 |
1002 | 签到题 | 一次遍历贪心解决即可, 1A |
1003 | 使用并查集解决欧拉路的问题 | 该问题可以转换为欧拉路的问题,同时使用并查集将整个图分为多个连通图,判断每个连通图是否为欧拉路,若均为欧拉图,则将每个图的度数以及各个图的联通加和即可,其中单个点的连通图未做单独处理导致迟迟不能AC,最终WA掉5次 |
1004 | 贪心题(需要将多种情况枚举清楚) | 对于问题中的情况,需要对多种情况做出枚举,第一次和第二次遍历情况较为特殊,第三次即以后的情况一样,对不同情况做出区分并加以判断即可,比赛中WA掉3次 |
1005-1008 | 1005数学博弈题,1007好像是树形DP | 1005-1008比赛时读过问题后放弃解决 |
由于很久未做算法题以及未写C++代码,并且多次WA掉,导致思路极为混乱,代码写的极为丑陋。由于昨日参加了初赛一,今日状态较昨日有所提升。继昨日之后再次于签到题WA掉3次,出师不利。AC三道, 罚时6次
1001
该题即为一个求2的n次方的问题,由于数字较大,使用快速幂取模即可,签到。
AC代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll mod = 998244353;
ll pow_(ll x, ll y, ll mod)
{
ll ans = 1;
ll base = x % mod;
while(y)
{
if(y & 1 != 0)
ans = ((ans%mod) * (base %mod))%mod;
y = y >> 1;
base = ((base%mod) * (base % mod) )%mod;
}
return ans % mod;
}
int main()
{
int T;
scanf("%d", &T);
while(T--)
{
ll a, b, k;
scanf("%lld%lld%lld", &a, &b, &k);
ll num = k / 2;
ll add_ = k % 2;
ll ansa = a;
ll ansb = b;
if(k > 0)
{
ansa = ((a%mod) * (pow_(2, num, mod)%mod)) % mod;
ansb = ((b%mod) * (pow_(2, num, mod)%mod)) % mod;
}
if(add_ == 0)
{
cout << (ansa + mod)%mod << " " << (ansb + mod)%mod << endl;
}
else
{
cout << (ansa + ansb + mod)%mod << " " << (ansa - ansb + mod)%mod << endl;
}
}
return 0;
}
1002
使用sort对数组进行一次排序,再使用一次遍历按照最优的规则即可,签到。
AC代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 10;
int T;
int a[maxn];
int main()
{
scanf("%d", &T);
while(T--)
{
int n, k;
memset(a, 0, sizeof(a));
scanf("%d%d", &n, &k);
for(int i=0; i<n; i++)
{
scanf("%d", &a[i]);
}
sort(a, a+n);
int count_ = 0;
int min_ = -1e9;
for(int i=0; i<n; i++)
{
int l = a[i] - k;
int r = a[i] + k;
if(min_ < l)
{
min_ = l;
count_++;
}
else if(min_ >= r)
{
continue;
}
else if(min_ >= l && min_ < r)
{
min_ += 1;
count_ ++;
}
}
printf("%d\n", count_);
}
return 0;
}
1003
将图中的连通图使用并查集进行分块操作,判断图中结点个数大于2的连通图的数量, 再进行判断每个连通图是否为欧拉图,进行上述两种操作后,对每个连通图的路径个数以及不同联通图的相加即获得正确答案。
AC代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1005;
int val[maxn][maxn];
char str[maxn];
int du[maxn];
int vis[maxn];
int par[maxn]; //父亲
int high[maxn]; //树的高度
void init(int n)
{
for(int i=0; i<n; i++)
{
par[i] = i;
high[i] = 0;
}
}
int Find(int x)
{
return par[x] == x ? x : par[x] = Find(par[x]);
}
void unit(int x,int y)
{
x = Find(x);
y = Find(y);
if(x==y) return ;
if(high[x]<high[y])
par[x] = y;
else
{
par[y] = x;
if(high[x]==high[y])
high[x] ++;
}
}
int main()
{
int T;
scanf("%d", &T);
while(T--)
{
int s, n;
scanf("%d%d", &s, &n);
n = n - 1;
memset(val, 0, sizeof(val));
memset(du, 0, sizeof(du));
memset(vis, 0, sizeof(vis));
init(s);
for(int i=0; i<s - 1; i++)
{
scanf("%s", str);
int len = strlen(str);
for(int j=0; j<len; j++)
{
if(str[j] == '0')
{
val[i+1][j] = 1;
val[j][i+1] = 1;
}
}
}
/*
for(int i=0; i<s; i++)
{
for(int j=0; j<s; j++)
{
printf("%d ", val[i][j]);
}
printf("\n");
}
*/
for(int i=0; i<s; i++)
{
int count_ = 0;
for(int j=0; j<s; j++)
{
if(val[i][j] == 1)
{
count_++;
unit(i, j);
}
}
du[i] = count_;
}
int ANS = 0; //几个连通块
for(int i=0; i<s; i++)
{
vis[Find(i)]++;
}
for(int i=0; i<s; i++)
{
if(vis[i] >= 2)
{
ANS++;
}
}
/*
for(int i=0; i<s; i++)
{
printf("%d ", vis[i]);
}
printf("\n");
for(int i=0; i<s; i++)
{
printf("%d ", du[i]);
}
printf("\n");
*/
int s_set = Find(n); //起点的连通集合
if(vis[s_set] == 1)
{
ANS++;
}
int s_du = du[n]; //起点的度
int count_all = 0;
int ans_all = 0;
if(s_du % 2 == 1)
{
for(int i=0; i<s; i++)
{
if(du[i] % 2 == 1)
{
if(Find(i) == s_set)
{
ans_all += du[i];
count_all++;
if(count_all >= 3)
{
ANS = -1;
break;
}
}
if(Find(i) != s_set)
{
ANS = -1;
break;
}
}
else if(du[i] % 2 == 0)
{
ans_all += du[i];
}
}
}
else
{
for(int i=0; i<s; i++)
{
if(du[i] % 2 == 1)
{
ANS = -1;
break;
}
else if(du[i] % 2 == 0)
{
ans_all += du[i];
}
}
}
if(ANS == -1)
cout << ANS << endl;
else
cout << (ANS - 1) * 2 + ans_all /2 << endl;
}
return 0;
}
1004
贪心算法,使用两种不同的前缀和进行求和计算,计算第一轮遍历后的最大值以及最终值。使用第二种前缀和的方法计算第二次遍历后的最大值以及最终值。第三次及其以后的情况相同。最后分情况讨论即可,比赛过程中WA掉3次,浪费大量时间。
AC代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll maxn = 100000 + 10;
ll a[maxn];
ll sum[maxn];
ll all[maxn];
int main()
{
int T;
scanf("%d", &T);
while(T--)
{
ll n, m;
ll max_ = 0, final_ = 0, sub_ = 0;
ll max_all = -1e9 - 10;
scanf("%lld%lld", &n, &m);
memset(a, 0, sizeof(a));
memset(sum, 0, sizeof(sum));
memset(all, 0, sizeof(all));
for(ll i=0; i<n; i++)
{
scanf("%lld", &a[i]);
}
if(a[0] < 0)
{
sum[0] = 0;
}
else
sum[0] = a[0];
if(sum[0] > max_)
{
max_ = sum[0];
}
all[0] = a[0];
if(all[0] > max_all)
{
max_all = all[0];
}
for(ll i=1; i<n; i++)
{
all[i] = all[i-1] + a[i];
if(all[i] > max_all)
{
max_all = all[i];
}
if(all[i] < 0)
{
if(all[i] * (-1) > sub_)
{
sub_ = all[i] * (-1);
}
}
sum[i] = sum[i-1] + a[i];
if(sum[i] < 0)
sum[i] = 0;
if(sum[i] > max_)
{
max_ = sum[i];
}
}
final_ = sum[n-1];
/*
//max_all 最大
//max_ 最大
// final_ 一轮终止
// sub_ 回撤
cout << max_all << endl;
cout << max_ << endl;
cout << final_ << endl;
cout << sub_ << endl;
*/
if(final_ == 0)
{
if(max_ >= m)
{
cout << "1" << endl;
}
else
{
cout << "-1" << endl;
}
}
else if(final_ > 0)
{
if(final_ > sub_)
{
if(max_ >= m)
{
cout << "1" << endl;
}
else
{
if(final_ + max_all >= m)
{
cout << "2" << endl;
}
else
{
ll ans = 0;
m = m - max_all;
m = m - final_;
ll num = m / (final_ - sub_);
ll k =m % (final_ - sub_);
ans = 2 + num;
if(k > 0)
ans++;
cout << ans << endl;
}
}
}
else if(final_ <= sub_)
{
if(max_ >= m)
{
cout << "1" << endl;
}
else
{
if(final_ + max_all >= m)
{
cout << "2" << endl;
}
else if(final_ + max_all < m)
{
cout << "-1" << endl;
}
}
}
}
}
return 0;
}
/*
5 5
1 -3 3 2 -2
*/