A. Cow and Haybales
题目大意: 给你n个数,你可以使得将相邻的数转移1,即一个加1,一个减1,你可以转移d次,问a1最大是多少。
核心思路贪心+模拟:从第 i 个位置转移到 1 的位置需要( i - 1 ) 步,优先从离 1 位置近的转移。
AC代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const double PI = acos(-1.0);
int main()
{
ios::sync_with_stdio(false);
int t;
while (cin >> t)
{
while (t--)
{
int n, d;
cin >> n >> d;
int a[105];
for (int i = 1; i <= n; i++)
cin >> a[i];
int cnt = 0;
for (int i = 2; i <= n; i++)
{
if (a[i])
{
if ((i - 1) * a[i] > d) //用完d
{
a[1] += (d / (i - 1));
break;
}
else //用不完d
{
a[1] += (a[i]);
d -= ((i - 1) * a[i]);
}
}
}
cout << a[1] << endl;
}
}
return 0;
}
B. Cow and Friend
题目大意让你从(0,0)−>(x,0),并且走的点的距离等于某个 ai 。问最小的步数。
方法一:
核心思路: 对 ai 进行从小到大排列,寻找大于等于x的 ai ,如果找到,则 ai=x 则就需要1步;如果 ai > x则需要 2 步;
如果找不到,则一次走的最大的值为 ai ,步数为 [ ai / x ] 向上取整。
AC代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const double PI = acos(-1.0);
const int maxn = 1e5 + 5;
int a[maxn];
int main()
{
ios::sync_with_stdio(false);
int t;
while (cin >> t)
{
while (t--)
{
int n, x, ans;
cin >> n >> x;
memset(a, 0, sizeof(a));
for (int i = 1; i <= n; i++)
cin >> a[i];
sort(a + 1, a + 1 + n);
int t = upper_bound(a + 1, a + 1 + n, x) - a; //比x大
if (t == 1 + n) //都比x小
{
if (x % a[n] == 0)
ans = x / a[n];
else
ans = x / a[n] + 1;
}
else //>x的
{
if (t > 1)
{
if (a[t - 1] < x)
ans = 2;
else
ans = 1;
}
else
ans = 2;
}
cout << ans << endl;
}
}
return 0;
}
方法二:
官方题解:
核心思路: 跟上面的思路是一样的,如果不能找到一步就走完的,就找到最大的向上取整。
官方AC代码:
#include <iostream>
#include <set>
#include <algorithm>
using namespace std;
set<int>a;
//you don't have to use set, it was just easier for us
int main(){
int T; cin>>T;
while (T--){
int N,X;
cin>>N>>X;
int far=0; //largest favorite number
for (int i=0;i<N;i++){
int A;
cin>>A;
a.insert(A);
far=max(far,A);
}
if (a.count(X)) //X is favorite number
cout<<1<<endl;
else
cout<<max(2,(X+far-1)/far)<<endl; //expression as explained in tutorial,向上取整的操作
a.clear();
}
}
C. Cow and Message
题目大意 给你一个字符串都是小写字母,然后让你找它的子序列,使得子序列中的字符程等差序列。并输出它的出现次数。
核心思路 DP
-
分析长度为 1 的子串,它就是自己本身出现的次数。
-
分析长度为 2 的子串,它就是状态转移方程为:表示 ( i , j) 位置出现的次数。
-
分析长度为 3 的子串,3的字串必定是有2的字串,他出现的次数定小于2子串出现的次数。
-
综上我们就分析长度为 1 和 2 的字串出现的次数即可。
AC代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const double PI = acos(-1.0);
ll cnt[26], dp[26][26];
ll ans;
int main()
{
ios::sync_with_stdio(false);
string s;
cin >> s;
int len = s.size();
for (int i = 0; i < len; i++)
{
int c = s[i] - 'a';
for (int j = 0; j < 26; j++)
dp[j][c] += cnt[j];
cnt[c]++;
ans = max(ans, cnt[c]);
}
for (int i = 0; i < 26; i++)
for (int j = 0; j < 26; j++)
ans = max(ans, dp[i][j]);
cout << ans << endl;
return 0;
}