2024牛客寒假算法基础集训营3(小白)

D:

思路:交换后暴力枚举所有前缀和再相减,取最大值

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e3+10;
int a[N];
int sum[N];
int n,k;
int ans=-1e9;
signed main()
{
    cin.tie(0);
    cout.tie(0);
     cin>>n>>k;
    if(!k)
    {
        for(int i=1;i<=n;i++)
        {
            cin>>a[i];
            sum[i]=sum[i-1]+a[i];
        }
        for(int l=1;l<=n;l++)
        for(int r=l;r<=n;r++)
        {
            ans=max(sum[r]-sum[l-1],ans);
        }
    }
    else 
    {
        for(int i=1;i<=n;i++) cin>>a[i];
        for(int i=1;i<=n-1;i++)
        {
            swap(a[i],a[i+1]);
            
        for(int j=1;j<=n;j++) {
            sum[j]=sum[j-1]+a[j];           
            
        }
            
        for(int l=1;l<=n;l++)
        for(int r=l;r<=n;r++)
        {
            ans=max(sum[r]-sum[l-1],ans);
        }
             swap(a[i],a[i+1]);
        }
    }
    cout<<ans<<endl;
}

J:

我的代码(错误的):就过了1/5,还是多刷题吧,总之多尝试吧,看不太懂题目想表达的意思。

#include <bits/stdc++.h>
using namespace std;
const int N=1e5+10;
double solve(vector<int> a[],vector<int> b[],int n,int m)
{
     int tt1=0;
    for(int i=1;i<=n;i++)
    {
        vector<int>::size_type num1 = a[i].size();
        if(num1>tt1)
        {
            tt1=i;
        }
    }
    double ans=0;
    int tag=0;
    for(int i=1;i<=m;i++)
    {
        int st=0;
        vector<int>::size_type num2 = b[i].size();
        (double)num2;
      for (auto item : b[i])
        {
            if (item == tt1)
            {
                st=1;
                break;
            }
        }
        if(st)
        {
            if(num2==1&&!tag) 
            {
                ans+=1;
                tag=1;
            }
            else if(num2>1)
            {
                ans+=(1-(1.0/num2));
            }
        }
    }
    return ans;
}
signed main()
{
    cin.tie(0);
    cout.tie(0);
    vector<int> a[N],b[N];
    int n,m,k;
    cin>>n>>m>>k;
    while(k--)
    {
       int x,y;
        cin>>x>>y;
        a[x].push_back(y);
        b[y].push_back(x);
    }
    double a1=solve(a,b,n,m);
    double a2=solve(b,a,m,n);
    cout<<"float"<<endl;
    printf("%0.8lf %0.8lf",a1,a2);
}

正确代码;

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int N = 1e5+9;
vector<ll> gu[N];
vector<ll> gv[N];
double du[N],dv[N];
double ans_1 = 0;
double ans_2 = 0;
 
int main()
{
    int n,m,k;cin>>n>>m>>k;
    for(int i=1;i<=k;i++)
    {
        int u,v;cin>>u>>v;
        gu[u].push_back(v);
        gv[v].push_back(u);
        du[u]++;//提前统计男生对应女生的数量
        dv[v]++;//提前统计女生对应男生的数量
    }
 
    double ans = 1;
    for(int i=1;i<=n;i++)
    {
        ans = 1.0;
        for(auto j:gu[i])
        {
            ans *= (1.0 - 1.0/dv[j]);
        }
        ans_1 += (1-ans);
    }
 
    for(int i=1;i<=m;i++)
    {
        ans = 1.0;
        for(auto j:gv[i])
        {
            ans *= (1.0 - 1.0/du[j]);
        }
        ans_2 += (1-ans);
    }
    cout<<"float\n";
    printf("%.8lf %.8lf",ans_1,ans_2);
 
    system("pause");
    return 0;
}

H:

有点懊恼,总是想不明白x[i],跟y[i]为什么会作为下标来比较,p[i]用于枚举所有可能,那就索性将p[x[i]]跟p[y[i]]当做a1,a2的未知值吧当所有条件满足就输出“yes”,应该不是这样理解的,求大神指导。

#include<bits/stdc++.h>
#define int long long
using namespace std;
int p[7777];
int x[5777],y[5777],z[5777];
void solve(){
    int n;
    cin>>n;
    for(int i=1;i<=n;i++){
    cin>>x[i]>>y[i]>>z[i];
    }
    for(int a=1;a<=3;a++){
        for(int b=1;b<=3;b++){
        for(int c=1;c<=3;c++){
            p[1]=a,p[2]=b,p[3]=c;
            int open=1;
            for(int i=1;i<=n;i++){
                if(z[i]==1){
                    if(p[x[i]]<p[y[i]]){
                         
                    }else open=0;
                }else {
                    if(p[x[i]]>=p[y[i]]){
                         
                    }else open=0;
                }
                 
            }
             
            if(open==1){
                puts("YES");
                return;
            }
          }
        }
    }
    puts("NO");
}
signed main(){
    int T=1;
    cin>>T;
    while(T--){
    solve();
    }
 
    return 0;
}

K:

明白意思,本来就不咋会建树,还被这个样例输出误导了

参考clmm_博客的(正确的):

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

原文链接:https://blog.csdn.net/clmm_/article/details/136083717

因为我们要按“完全二叉树”的模式建树,也就是从上到下,从左往右建树。这个可以想到遍历二叉树,用的是队列

if (b % 2 == 1 && r % 2 == 0 && b >= r / 2 && b <= 1 + 2 * r)这个自己找一下规律就可以判断

void solve() {
	int b, r; cin >> b >> r;
	queue<int> q;//1代表黑,0代表红
	q.push(1);
 
	if (b % 2 == 1 && r % 2 == 0 && b >= r / 2 && b <= 1 + 2 * r) {
		cout << "Yes" << endl;b--;
		int cur = 2;
		while (!q.empty()) {
			int t = q.front(); q.pop();
			if (t == 1) {
				//要给它红孩子
				if (r == 0) cout << "-1 -1" << endl;
				else {
					cout << cur; cur++;
					cout << " " << cur << endl; cur++;
					q.push(0);
					q.push(0);
					r -= 2;
				}
			}
			else {
				if (b == 0) cout << "-1 -1" << endl;
				else {
					cout << cur; cur++;
					cout << " " << cur << endl; cur++;
					q.push(1);
					q.push(1);
					b -= 2;
				}
			}
		}
	}
	else cout << "No" << endl;
 
}

M:

我的代码(错误的):

利用两个字符串输入,暴力枚举所有组合,再用stol()将两个字符串转化为数字%36。

(只过了一半的数据,超时了还)

#include <bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int a[N];
signed main()
{
    cin.tie(0);
    cout.tie(0);
    int t;
    cin>>t;
    for(int i=1;i<=t;i++)
    {
        cin>>a[i];
    }
    int count=0;
    for(int i=1;i<=t;i++)
    {
         string s=to_string(a[i]);
        for(int j=1;j<=t;j++)
        {
           string s1=to_string(a[j]);
            int n1;
            if(i!=j)
            {
                n1=stol(s+s1);
               if(n1%36==0) count++;
            }
        }
    }
    cout<<count<<endl;
}

参考clmm_博客的(正确的):

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

原文链接:https://blog.csdn.net/clmm_/article/details/136083717

分析:看到题目的时候想,36的倍数都有什么特点,因为之前做过一道题好像也是关于什么的倍数,是有规律可循的,但在这题不行,要另找思路。

这题的正确思路是列出式子,然后变形,涉及到模运算的变换公式-CSDN博客。

原文链接:https://blog.csdn.net/clmm_/article/details/136092224

对于(ai,aj)组成的数,若是36的倍数,列出

(ai* + aj) %36 = 0,k是aj的位数

[(ai*)%36 + aj%36] % 36 = 0

[ [(ai%36)*(%36)] % 36 + aj%36 ] %36 = 0

从1-n枚举每一个数当aj,去查询有没有 ai 满足 [(ai%36)*(%36)] % 36 = 36 - aj%36。

事先用哈希表存每个数%36的结果,这样查询的时候就从哈希表的1-35找

总的时间复杂度是O(n)             

​
#include <bits/stdc++.h>
#define int long long
#define rep(i,l,r) for(int i=1;i<=n;i++)
using namespace std;
const int N=1e5+10;
//0是任何数的倍数
string s[N];
int a[N], b[37];
void solve() {
    int n; cin >> n;
    rep(i, 1, n) {
        cin >> s[i];
        a[i] = atol(s[i].c_str());//c_str()就是将C++的string转化为C的字符串数组
        b[a[i] % 36]++;
    }
 
    int ans = 0;
    rep(j, 1, n) {
        int k = s[j].size();//*10的位数
        int pj = a[j] % 36;//后半段%36的值(a[j])%36
        int key = (36 - pj) % 36;
        int tpm = (int)pow(10, k) % 36;//相当于前半部分取模的值(a[i]*10的k次方)%36
        for (int i = 0; i <= 35; i++) {
            if ((i * tpm) % 36 == key) {
                ans += b[i];
                if (pj == i) ans--;//不太清楚,可能是用同一个的数组合%36也是答案,所以减一吧
            }
        }
 
    }
    cout << ans << endl;
}
signed main()
{
    cin.tie(0);
    cout.tie(0);
    solve();
}

​

  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值