A题:
解题思路:
分两种情况
1.n小于k的情况,那么就是要把k平均分成n份,如果说不能平均分,那么就有一份会多出1(不可能多出2,因为余数是2的话那么就被其他的份接收了,即此时最大值有两个).
2.n大于k的情况,让k大于n( 即k=k*(n/k) )就可以了,变成上面的情况
代码:
#include<iostream>
using namespace std;
int main()
{
int t;
cin >> t;
while (t--)
{
int n, k;
cin >> n >> k;
int temp = k % n ? 1 : 0;
if (n > k) {
temp = n % k ? 1 : 0;
k = k * ((n / k) + temp);
}
int ans = k / n;
cout << ans + temp << endl;
}
}
B题(别人的题解):
既然是前缀和的占比,并且第一个是 a[1] 没有前缀和,那么我们把所有增加量都放在 a[1] 即可。
从左往右遍历,找到不符合条件的数,并用其增加量来更新答案取最大值就好。
#include<iostream>
#include<cstring>
using namespace std;
#define ll long long
ll a[200001], b[200001];
ll max(ll a1, ll a2) {
return a1 > a2 ? a1 : a2;
}
int main()
{
int t;
cin >> t;
while (t--)
{
ll ans = 0 , n, k;
cin >> n >> k;
for (int i = 1; i <= n; i++) {
cin >> a[i];
b[i] = b[i - 1] + a[i];
}
for (int i = 2; i <= n; i++) {
ll temp = 100 * a[i] - b[i - 1] * k ;
if (temp > 0) { ans = max(ans, temp); }
}
cout << ans / k + (ans % k ? 1 : 0) << endl;
memset(a, 0, sizeof(a));
memset(b, 0, sizeof(b));
}
}
C题(别人的题解):
链接:https://blog.csdn.net/weixin_45750972/article/details/113439070
题意
给定n条链,每条链有ci个点,给定第i条链的首尾点与前一条链相连的关系,求最长简单环长度
贪心,显然答案肯定是一段连续的链区间,我们只需考虑对于当前第i ii条链,如果作为起点更优就更新,否则就充当中间链,注意特判下首尾点连向相同点的情况,这种情况必须截断,重新设置起点。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+5,M=2e4+5,inf=0x3f3f3f3f,mod=1e9+7;
#define mst(a,b) memset(a,b,sizeof a)
#define PII pair<int,int>
#define fi first
#define se second
#define pb push_back
int t,n,a[N],b[N],c[N];
int main(){
scanf("%d",&t);
while(t--){
scanf("%d",&n);for(int i=1;i<=n;i++) scanf("%d",&c[i]);
ll ans=0;
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
for(int i=1;i<=n;i++) scanf("%d",&b[i]);
ll x=a[2],y=b[2];
ll tmp=abs(x-y)+2;
for(int i=2;i<n;i++){
if(a[i+1]==b[i+1]){
ans=max(ans,tmp+c[i]-1);
tmp=2;
}
else {
ans=max(ans,tmp+c[i]-1);
if(tmp+c[i]-1-abs(a[i+1]-b[i+1])<abs(a[i+1]-b[i+1])) tmp=abs(a[i+1]-b[i+1])+2;
else tmp=tmp-1+c[i]-abs(a[i+1]-b[i+1])+2;
}
}
tmp=tmp+c[n]-1;
printf("%lld\n",max(tmp,ans));
}
return 0;
}
D题:
由题目可知:既然要让这个前后缀小于k(即让字符串的前后缀最小),那么我们就直接abcabcab…那样就前后缀为0即小于k.
代码:
#include<iostream>
#include<string>
using namespace std;
string a;
int main() {
int T;
scanf("%d",&T);
while (T--) {
int n, k;
cin >> n >> k;
for (int i = 0; i < n; i++) {
printf("%c",'a'+i%3);
}
printf("\n");
}
return 0;
}
E题:
解题思路:
两种方法:
1.先找形状为.的树,再找形状为.^,的树,以此类推,但是时间复杂度很高,不是好的算法
TLE代码如下:
#include<iostream>
#include<cstring>
using namespace std;
char a[500][500];
int dy[] = { 0,-1,1 };
int n, m, ans;
int zz = 0;
void find(int x, int y, int k)
{
//cout << "x=" << x << "y=" << y << endl;
int tx,ty;
if (k <= 0) { return; }
for (int i = 0; i < 3; i++) {
tx = x + 1;
ty = y + dy[i];
if (tx < 0 || tx >= n || ty >= m) {
zz = -1; return;
}
if (a[tx][ty] != '*') { zz = -1; return; }
}
for (int i = 0; i < 3; i++) {
tx = x + 1;
ty = y + dy[i];
find(tx, ty, k - 1);
}
return;
}
void dfs(int step)
{
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if(a[i][j]=='*') {
zz = 0;
find(i, j, step);
if (zz == 0)ans++;
}
}
}
return;
}
int main() {
int T;
cin >> T;
while (T--) {
cin >> n >> m;
for (int i = 0; i < n; i++) {
cin >> a[i];
}
for (int i = 0; i < n; i++) {
dfs(i);
}
cout << ans << endl;
ans = 0;
}
return 0;
}
方法2:
从下往上找,找到为’*'的点,就让这个点对应的值为1加上下面三个格子的值其中的最小值:
#include<iostream>
#include<cstring>
using namespace std;
int n, m, v[600][600];
char a[601][601];
long long ans;
int min(int a1, int a2) {
return a1 < a2 ? a1 : a2;
}
int min(int a1, int a2, int a3) {
return a1 < min(a2, a3) ? a1 : min(a2, a3);
}
void func1()
{
int i, j;
for (i = n-1; i >= 0; i--) {
for (j = 0; j < m; j++) {
if (a[i][j] == '*') {
v[i][j] = 1;
v[i][j] += min(v[i + 1][j], v[i + 1][j - 1], v[i + 1][j + 1]);
//cout << "i=" << i << ",j=" << j << ",v[i][j]="<<v[i][j]<<endl;
}
}
}
}
void func2()
{
int i, j;
for (i = 0; i < n; i++) {
for (j = 0; j < m; j++) {
ans += v[i][j];
}
}
}
int main()
{
int T;
cin >> T;
while (T--) {
cin >> n >> m;
for (int i = 0; i < n; i++)cin >> a[i];
func1();
func2();
cout << ans << endl;
ans = 0;
memset(v, 0, sizeof(v));
memset(a, 0, sizeof(a));
}
}
F题(别人的题解):
思路:
对于后缀序ai,ai+1,…,an如果该序列已经全部满足ai=i,那么对于任意的r∈[i,n],他们是否排序都不会影响最终答案。但是如果不是这种序列就必须保证最后一个ai!=i必须有r=i,并且进行概率为p的操作。而后面的操作是否进行实际上都不影响答案,如果不进行刚才的操作,就必须保证r>i的操作至少进行一次。因此答案需要累加r>i的每钟操作一次。特判一下整个序列都已经从小到大排好的情况,此时答案为1.
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+50;
int T,n,m,a[maxn];
struct Node{
int f;double q;
}t[maxn];
int cmp(Node x,Node y){
return x.f<y.f;
}
int main(){
cin>>T;
while(T--){
cin>>n>>m;
for(int i=1;i<=n;i++)cin>>a[i];
for(int i=1;i<=m;i++)cin>>t[i].f>>t[i].q;
sort(t+1,t+1+m,cmp);
int s=0;
for(int i=n;i>=1;i--){
if(a[i]!=i){
s=i;
break;
}
}
double ans=0,sum=1.0;
for(int i=m;i>=1;i--){
if(t[i].f>=s){
ans=ans+sum*t[i].q;
sum*=(1-t[i].q);
}
else{
break;
}
}
if(s==0)ans=1.0;
printf("%.7lf\n",ans);
}
return 0;
}