【组合数算法】以及校赛小复盘

HUSTOJ

这题真的不难,比赛的时候对字符串数组不熟悉

复盘感觉当时应该错了两点细节

字符串真的好多细节

C++中输入字符串的几种方法_c++输入字符串_lixiaoyu20106587的博客-CSDN博客

C++字符串的几种输入方法(string和字符数组)_c++string输入_WY.Lan的博客-CSDN博客

#include <bits/stdc++.h>
using namespace std;
const int N=15;
int n,m;
string the[N];
string a[N];
string b[N];
int main()
{
   scanf("%d%d",&n,&m);
   for(int i=0;i<n;i++)
   {
           cin>>the[i];//待翻译语句 
   }
   for(int i=0;i<m;i++)
   {
           cin>>a[i];
           getchar();//实验一下就会发现这里如果没有getchar,b[i]就成了‘\n'
           getline(cin,b[i]);//注意b[i]记录的是一行语句,用cin遇到空格会断开
   }
   for(int i=0;i<n;i++)
   {
           for(int j=0;j<m;j++)
           {
               if(the[i]==a[j])
               {
                   //the[i].replace(0,sizeof the[i],b[j]);
                   the[i]=b[j];//两种方式都对
            }
         }
   }
      for(int i=0;i<n;i++)
       {
           cout<<the[i]<<" ";//待翻译语句 
       }
   return 0;
}

基本没什么逻辑,只要检查输入的对不对,调试一下,注意细节就完了。

感觉没AC的主要原因是,这题没放在签到题的位置,乐。

#define int long long

使用

如果有题目死活 WA 调不出来,可以 define 一下看看是不是溢出所导致的错误。如果是,再把 define 去掉,好好思考一下是哪里溢出了。查有没有爆int的时候,这毕竟是最快的方法。

#define int long long 以后 要写 signed main()

扫描二维码关注公众号,回复: 14729119 查看本文章

在OI中,将int 宏定义 为 long long是不是一种合理的技巧? - 知乎 (zhihu.com)

【C++疑问】signed main 和 int main 的区别?_ZSYL的博客-CSDN博客

缺点:

1.long long 不仅费空间,也费时间,容易 MLE/TLE

ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);

看大佬的代码真的能学到好多,这是真大佬。。。

ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
//节省许多时间,使效率与scanf与printf相差无几.

丘丘兵团

HUSTOJ

我的第一想法是求最小子列和,然而我不会。。。

先直接copy一下大佬的代码,对着样例模拟了一下思路,妙啊妙啊这也能二分。(本蒟蒻留下了没见识的泪水。

蒟蒻分析一下,如果遍历一遍k然后再去遍历数组求和比较的话时间复杂度是On方,然而对于100%的数据,1 <= n <= 1e6, 1 <= x, ai <= 1e9,大g特g

那就二分一遍k呗,妙啊~~~

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e6 + 10;
int a[N], n, x;
bool check (int k) {
    ll sum(0);
    for (int i = 1; i <= n; i++) {
        sum += a[i];
        if (i < k) continue;//要加上mid个 
        
        if (sum < x) return false;
        //但凡存在一组的sum<x,直接返回false
         
        sum -= a[i - k + 1];//往右边移动 
    }
    return true;//如果每一个都满足就返回true 
}
void solve() {
    cin >> n >> x;
    
    for (int i = 1; i <= n; i++)
        cin >> a[i];
        
    //这里的二分相当于二分k 
    int l = 1, r = n, res(0);
    while (l <= r) {
        int mid = (l + r) >> 1;
        if (check(mid)) 
            r = (res = mid) - 1;
        //如果对这个mid都满足条件,那么就mid-- 
        else l = mid + 1;
    }
    cout << res << '\n';
}
signed main() {
    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    //节省许多时间,使效率与scanf与printf相差无几.
    solve();
    return 0;
}

跟大佬的基本差不多,思路就是二分k,然后遍历数组求和。

#include <bits/stdc++.h>
using namespace std;
const int N=1e6+10;
int n,x;
int a[N]; 
long long sum;
bool check(int k)
{
    sum=0;
    for(int i=1;i<=n;i++)
    {
        sum+=a[i];
        if(i<k) continue;//要加上x个 
        if(sum<x) return false;
        sum-=a[i-k+1];
    }
    return true;
    
}
int main()
{
   scanf("%d%d",&n,&x);//数组大小,和要求的人数 
   for(int i=1;i<=n;i++)
   {
           scanf("%d",&a[i]);
   } 
   
   int l=1,r=n,res=0;  
   while(l<=r)
   {
           int mid=(l+r)>>1;
           if(check(mid))
           {
               res=mid;
               r=mid-1;
        }else l=mid+1;
   }
   cout<<res<<endl;; 
   return 0;
}

组合数算法

参考:C++求解组合数的具体实现_组合数c++_AlbertS的博客-CSDN博客

int combine(int n,int m)
{
    int ans=1;
    if(n==m||m==0) return 1;
    m=min(m,n-m);
    for(int i=1;i<=m;i++)
    {
        ans=ans * (n-i+1) / i;
    }
    return ans;
}

猜你喜欢

转载自blog.csdn.net/m0_74183164/article/details/129720705