开学大二补题(第二周)

这几天比赛发现短板很明显,写题异常慢,但是题是可以写出来的

还有就是wa的太随便动不动就是一个很简单的点给我wa了

总之,题刷少了

Problem - H - Codeforces

题意:就是给你一个棵树,这棵树分很多的叶子 一共n个点   然后让你对这个树进行层减

一共减k层 就是一层一层的去掉,然后输出还剩点的个数

 

题解:这道题就是一个拓扑排序的题

很好想,一层一层搞我们发现就和这些点的边数有关边数少的绝对最最低层

所以我们可以记录每一个点连起来的边数只要出度为1那么这个点就是最底层的点我们就删除即可

然后跑一个广搜    这样的首先记录现在就是1的底层点如何入队就可以了

跑队列的时候就用这些1的点因为底层的点被我们剪掉了,所以边也没了,和这些底层相连的点边数就要减减,然后减完看看这个点是不是边数只有1了

如果是那么然后减的层数不够,这点就入队,够就不入队,就行了

#include <bits/stdc++.h>
#pragma  GCC optimize("Ofast")
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <cmath>
//#define double long double
#define int long long
//#define endl '\n';
using namespace std;
const int N=1e6+5,M=1e1;
const int INF = 0x3f3f3f3f;
const int mod=998244353;
typedef pair<int,int> PII;
int bian[N];

int n1,k1;
int dep[N];
vector<int> a[N];
int su;
void bfs(int n,int k)
{
    queue<int> q;
    for(int i=1;i<=n;i++)
    {
        if(bian[i]==1)
        {
            q.push(i);
            bian[i]=0;
            su++;
            dep[i]=1;
        }
    }
    while (!q.empty())
    {
        int u=q.front();
        q.pop();
        for(auto x:a[u])
        {
            bian[x]--;
            if(bian[x]==1 && dep[u]<k)
            {
                su++;
                q.push(x);
                dep[x]=dep[u]+1;
            }
        }
    }
}
void solve() {

    cin>>n1>>k1;
    for(int i=1;i<=n1;i++) bian[i]=0, dep[i]=1, a[i].clear();
    su=0;
    for(int i=1;i<n1;i++)
    {
        int x,y;
        cin>>x>>y;
        a[x].push_back(y);
        a[y].push_back(x);
        bian[x]++;
        bian[y]++;
    }
    if(n1==1 || 2*k1>=n1)
    {
        cout<<0<<endl;
        return;
    }
        bfs(n1,k1);
        cout<<n1-su<<endl;



}


signed main(){
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    int T=1;
    cin>>T;
    while(T--){
        solve();
    }
    return 0;
}

 Problem - E - Codeforces

题意:给你两种汤   第一次就是只有第一种汤,第二次是只有第二种汤,然后后面开始就把两种汤混合就行了不断混合

就是i-2次和i-1次混合出来就是第i次,不断递推下去,然后问你第n次两种汤比例是多少

 

题解: 其实手推的时候就会发现越是往后越是靠近1:3的比例,所以我们就知道后面大的数输出一个固定值就行了

这个点也是我卡的点(赛时卡死了)

然后前面的我们就稍微写一下模拟即可,不断相加除2不断减半即可

#include <bits/stdc++.h>
#pragma  GCC optimize("Ofast")
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <cmath>
//#define double long double
#define int long long
//#define endl '\n';
using namespace std;
const int N=1e6+5,M=1e1;
const int INF = 0x3f3f3f3f;
const int mod=998244353;
typedef pair<int,int> PII;



void solve()
{
    int n;
    cin>>n;
    if(n==1)
    {
        cout<<100<<" "<<0<<endl;
        return;
    }
    if(n==2)
    {
        cout<<0<<" "<<100<<endl;
        return;
    }
    if(n==3)
    {
        cout<<50<<" "<<50<<endl;
        return;
    }
    if(n>=28)
    {
        cout<<"33.333333 66.666667"<<endl;
        return;
    }
    double a=100,b=0;
    for(int i=3;i<n;i++)
    {
        double t=a;
        a=b;
        b=t/2+b/2;
    }
    double ans=a*1.0/2+b*1.0/2;
    printf("%.6lf %.6lf",ans,100-ans);
}


signed main(){
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    int T=1;
//    cin>>T;
    while(T--){
        solve();
    }
    return 0;
}

 Problem - L - Codeforces

题意:(这道题其实还算是比较简单的,思路很好想,只是赛事卡题了这道题没有去写)

给你一块l*w的地,然后给你n个种类的种子,让你用n个种子去等面积的种植,并且构造出这个矩阵。

 

题解:题意很简单,题的思路也是一下可以想到的,就是不太好实现,但是问题不大

l*m的矩阵我们手推一下就可以发现只要l*m%(种类数)可以除尽,那么我们就一定可以用这些种子等面积的种植在这块地里

然后我们在手推一下,如何种植呢,直接l*w/n就是一块地的面积然后对长和宽取gcd就可以知道你要的小矩形的长和宽了

然后模拟一下打出来即可

#include <bits/stdc++.h>
//#pragma  GCC optimize("Ofast")
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <cmath>
//#define double long double
#define int long long
//#define endl '\n';
using namespace std;
const int N=100+9,M=1e1;
const int INF = 0x3f3f3f3f;
const int mod=998244353;
typedef pair<int,int> PII;

char a[N][N];
char c[N];
void solve()
{
     int l,w,n;
     cin>>l>>w>>n;
     if(l*w%n!=0)
     {
         cout<<"IMPOSSIBLE"<<endl;
     }
     else {
         int sum = l * w / n;
         int chang = __gcd(sum, l);
         sum/=chang;
         int kuan = __gcd(sum, w);
         char f = 'A';
         for (int i = 1; i <= w / kuan; i++) {
//             cout<<f<<endl;
             c[i] = f;
             f += 1;

         }

         for (int i = 1; i <= l; i++) {
             int x = 1;
             for (int j = 1; j <= w; j++) {
                     cout<<c[x];
                 if (j % kuan == 0)
                     x++;
             }
             cout<<endl;
             if (i % chang == 0) {
                 for (int k = 1; k <= w/kuan; k++) {
                     c[k] += w/kuan;
                 }
             }

         }
     }
//         for(int k=1;k<=l;k++)
//         {
//             for(int p=1;p<=w;p++)
//             {
//                 cout<<a[k][p];
//             }
//             cout<<endl;
//         }


}


signed main(){
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    int T=1;
//    cin>>T;
    while(T--){
        solve();
    }
    return 0;
}

 Problem - I - Codeforces

题意:让你买东西,给你n和m,n是一共多少天,m是最多可留m天,第一个月买进然后在第i个月卖出,然后会给你第i个月卖出的价格,并且当你卖出的时候一定要买出,然后会给出当月买入的价格,必须买入,并且,你不能一直留着,连续m天后必须卖出,然后结尾要在n+1天后卖出,不需要买入了

现在问你,什么时候卖出和买入可以让总支出价格最低

 

题解:一看就是一个dp,只要推出状态即可

首先开一个dp[i]   代表改天的最优价格

然后我们就推状态吧

首先初始化

 给n+1天赋一个0头,代表该天的时候不需要买入

后面的dp是直接第一天买入

开始推状态首先我们先一个for遍历n+1天

然后又一个for对前i天进行优化

首先在没有满m天的时候我们可以判断一下需不需要卖出和买进

 

a[i][0]就是买进,然后在a[j][i-j]这是卖出的价格

然后到m天了,必须卖出

 最后输出n+1即可

#include <bits/stdc++.h>
//#pragma  GCC optimize("Ofast")
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <cmath>
//#define double long double
#define int long long
//#define endl '\n';
using namespace std;
const int N=500010,M=1e1;
const int INF = 0x3f3f3f3f;
const int mod=998244353;
typedef pair<int,int> PII;


int dp[N];
vector<int> a[N];
void solve()
{

    int n,m;
    cin>>n>>m;
    for(int i=1;i<=n;i++)
    {
        for(int j=0;j<=min(m,n-i+1);j++)
        {
            int x;
            cin>>x;
            a[i].push_back(x);
        }
    }
    a[n+1].push_back(0);
    dp[1]=a[1][0];
    int o=1;
    for(int i=2;i<=n+1;i++)
    {
        for(int j=max(o,i-m);j<i;j++)
        {
            if(j>max(o,i-m))
            {
                dp[i]=min(dp[i],dp[j]+a[i][0]-a[j][i-j]);
            }
            else
            {
                dp[i]=dp[j]+a[i][0]-a[j][i-j];
            }
        }
    }
    cout<<dp[n+1];
}


signed main(){
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    int T=1;
//    cin>>T;
    while(T--){
        solve();
    }
    return 0;
}

 

然后是我的弱项

图:

P1144 最短路计数 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

题意:给你n和m,并且给你一个图,就是点和点相连的图,然后让你找最短路,从1到每一个点的最短路,问你到每一个点最短路有多少种走法

 

题解:用一个邻接表来存图吧

然后我们来想一下怎么走这个最短路,我们发现一个点最短路一定经过了一个层数比它少一的结点(否则不是最短路)。

所以我们直接来广搜即可

看代码注释理解,这里就不过多赘述,模板题

#include <bits/stdc++.h>
//#pragma  GCC optimize("Ofast")
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <cmath>
//#define double long double
#define int long long
//#define endl '\n';
using namespace std;
const int N=100005,M=1e1;
const int INF = 0x3f3f3f3f;
const int mod=100003;
typedef pair<int,int> PII;

vector<int> a[N];   //存图
int sum[N];    //这个数组是用来计数的,就是最后输出的答案
int vis[N];    //这个是用来标记的,防止重复跑一个点
int dep[N];    //用来记步数,看看走了多少步
void bfs(int x)
{
    queue<int> q;
    dep[x]=0;
    vis[x]=1;
    q.push(x);
    sum[x]=1;   //初始化,点1
    while (!q.empty())
    {
        int op=q.front();
        q.pop();
        for(int i=0;i<a[op].size();i++)
        {
            int t=a[op][i];
            if(!vis[t])
            {
                vis[t]=1;      //标记这个点已经走过了
                dep[t]=dep[op]+1;   //意思就是上一个点加1就到现在这一个点了,不断计数,看看几步到
                q.push(t);    //把现在这个点在放进去,再从这点开始想其他点跑
            }
            if(dep[t]==dep[op]+1)    //如果遇到了一个点加1就是当前点,那么这个点加一就是当前的最短路了
            {
                sum[t]=(sum[t]+sum[op])%mod;   //到op这个点的次数加上原来有的就是从一到t最短路的次数了
            }
        }

    }
}


void solve()
{
    int n,m;
    cin>>n>>m;
    for(int i=1;i<=m;i++)
    {
        int x,y;
        cin>>x>>y;
        a[x].push_back(y);
        a[y].push_back(x);
    }
    bfs(1);  //从点1开始想其他点跑
    for(int i=1;i<=n;i++)
    {
        cout<<sum[i]<<endl;
    }
}


signed main(){
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    int T=1;
//    cin>>T;
    while(T--){
        solve();
    }
    return 0;
}

 交互题

Problem - A - Codeforces

题解:这题基本没什么思维,主打就是暴力,问题出在交互上,就是你要给出一个字符串

然后交互让他给你判断代码对错时的运行时间,你输出的字符串符合它给的时间,那就对了

 

思路:首先就是确定字符串的长度,大于5ms长度就对了,然后我们在一个位置一个位置去判断,一共才(字符)62*20,小于2500次所以放心暴力即可

换一个字符就问一下时间,直到时间变大,那个时候就是这个位置的字符对了,然后就可以进行下一个位置了

找位置就是(t-5)/9,就是错的位置

注意交互我们在每一个输出后面加上 fflush(stdout);进行交互

#include<iostream>
#include<algorithm>
#include<vector>
#include<set>
#include<queue>
#include<math.h>
#include<stack>
#include<map>
#include<list>
#include<unordered_set>
#include<unordered_map>
//#define endl '\n';
//#define int long long;
using namespace std;
typedef long long ll;
const int N = 2e5+10;
int n, m, k;
char ans[100] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
string tmp;

void sovle(){
    int len = 1;
    string s = "a";
    string s1,ss;
    int t;
    for (int i = 1; i <= 20; i ++){
        cout << s << endl;
        fflush(stdout);
        cin>>s1>>ss;
        scanf(" (%d ms)",&t);
        if (t == 5){
            s += 'a';
        }
        else {
            len = i;
            break;
        }
    }
    int last=0;
    for (int i = 0; i < len; i ++)tmp+= 'a';
    cout<<tmp<<endl;
    fflush(stdout);
    cin>>s1>>ss;
    scanf(" (%d ms)", &t);
    last = t;
    int pos=(t-5)/9;
    for (int i = pos-1; i < len; i ++){
        for (int j = 0; j < 62; j ++){
            tmp[i] = ans[j];
            cout << tmp << endl;
            fflush(stdout);
            cin>>s1>>ss;
            scanf(" (%d ms)", &t);
            if(last<t) {
                last = t;
                int y=(t-5)/9;
                i=y-2;
                break;
            }
        }
    }
}

int main()
{
    int t = 1;
    //scanf("%d", &t);

    while (t --){
        sovle();
    }

    return 0;
}

 

posted @ 2023-09-12 19:54  whatdo+  阅读(3)  评论(0编辑  收藏  举报