ACM10.16-10.21作业

P8682 [蓝桥杯 2019 省 B] 等差数列

找到最短的等差数列

即 1) 找到公差d

2)找到最大和最小项

公差d的找法就是找出满足输入数的最大的公差

即找到相差最小的两个数的差 作为公差d

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int n;
    cin>>n;
    int a[1000000];
    for(int i=0;i<n;i++)
    {
        cin>>a[i];
    }
    sort(a,a+n);
    int d=a[1]-a[0];
    for(int i=0;i<n;i++)
    {
        if(a[i+1]-a[i]<d&&a[i+1]>=a[i]){d=a[i+1]-a[i];
        }
    }
if(d==0) cout<<n;
    else cout<<(a[n-1]-a[0])/d+1;
    return 0;
 } 

P1226 【模板】快速幂

本题主要难点出在数据比较大

则考虑使用pow(a,n)=pow(a*a,n/2)的方式减少时间复杂度

由于数据较大 所以每次计算完取模计算 保证数据不超

#include<bits/stdc++.h>
using namespace std;
long long f(long long a,long long b,long long p)
{
    long long    ans=1;
while(b>0)
{
    if(    b%2!=0){
        ans=ans*a;
        ans%=p;
    }
    a=a*a;
    a=a%p;
    b=b/2;
    
 } 
    return ans%p;
 } 
int main()
{
long long a,b,p;
cin>>a>>b>>p;
long long k=f(a,b,p)+p;

cout<<a<<"^"<<b<<" mod "<<p<<"="<<k%p;
 } 

P2249 【深基13.例1】查找

本题难点也是数据量大

为了减少时间复杂度 使用二分查找

时间复杂度为o(nlogm)

考虑使用lower_bound二分查找出第一个大于等于x的数据的地址

(upper_bound是找出第一个大于的数据的地址)

由于是地址 所以需要-a

ps:若需要找到一个小于等于的为lower_bound(begin,end,x,greater<type>())

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int n,m;
    cin>>n>>m;
    int a[n];
    for(int i=0;i<n;i++)
    {
        cin>>a[i];
    }
    sort(a,a+n);
    while(m)
    {
        int x;
        cin>>x;
        int ans=lower_bound(a,a+n,x)-a;
        if(x!=a[ans]) printf("-1 ");
        else printf("%d ",ans+1);
        m--;
    }
    return 0;    
}

P1223 排队接水

思路比较自然 找出最小的先往前排 再计算总和

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int n;
    cin>>n;
    int a[n],t[n],s[n];
    for(int i=0;i<n;i++)
    {
        cin>>a[i];
        t[i]=a[i];
    }
    int mx=0;
    int m=n;
    int j=0;
    while(m)
    { mx=10000000;
        for(int i=0;i<n;i++)
        {
            if(t[i]<mx) {s[j]=i;mx=t[i];
            }
        }
        t[s[j]]=10000001;
        cout<<s[j]+1<<" ";
        if(m==1) cout<<endl;
        m--;
        j++;
    }
    double sum=0;
    for(int i=0;i<n;i++)
    {
        sum+=a[s[i]]*(n-1-i);
    }
    
    sum=1.0*sum/n;
    cout<<fixed<<setprecision(2)<<sum;
    return 0;
 } 

P1803 凌乱的yyy / 线段覆盖

贪心算法

排序以后贪心 找到最早结束的一个时间

注意用sort结构体的排序 从小到大排序

#include<bits/stdc++.h>
using namespace std;
int last=0;
struct oi
{
    int a,b;
}arr[10000000];
bool cmp(oi x,oi y)
{
return x.b<y.b;
}
int main()
{
int n;
cin>>n;
int ans=0;

for(int i=0;i<n;i++)
{
    cin>>arr[i].a>>arr[i].b;

}
sort(arr,arr+n,cmp);
for(int i=0;i<n;i++)
{
    if(arr[i].a<last) continue;
    ans++;
    last=arr[i].b;
 } 
 cout<<ans;
    

}
 

P1031 [NOIP2002 提高组] 均分纸牌

只需要从第一项开始看

让第二项取给或者收 第一项少的或多的牌

如果正好则不计入次数

#include<bits/stdc++.h>
using namespace std;
bool cmp(int a, int b)
{
    return a>b;
}
int main()
{
    int n;
    cin>>n;
    int a[n];
    int total=0;
    int k;
    for(int i=0;i<n;i++)
    {
        cin>>a[i];
        total+=a[i];
    }
    k=total/n;
    
    int ans=0;
    for(int i=0;i<n;i++)
    {
        if(a[i]==k) continue;
        else if(a[i]!=k) {
        a[i+1]+=a[i]-k;
        ans++;
    }

}
cout<<ans;
    return 0;
 } 

P1824 进击的奶牛

最大值的最小和最小值的最大考虑使用二分法

难点为check(int x)函数 

我的思路是先排序,从最小的数开始找 找到第一个满足距离大于x的另一个牛栏

计算能找的数量总和是否满足

再使用二分法从0 到a[n-1]中找到满足的最大的x为答案

#include<bits/stdc++.h>
using namespace std;
int n,c,a[10000000];
bool check(int x)
{
int k=a[0];
int ans=1;
for(int i=1;i<n;i++)
{
    if(a[i]-k>=x) {
        k=a[i];
        ans++;
}
}
if(ans>=c) {
    return true;
}
else return false;
}
int main()
{
    
    cin>>n>>c;
    
    for(int i=0;i<n;i++)
    {
        cin>>a[i];
    }
    sort(a,a+n);
    int left=0,right=a[n-1];
    int mid=(left+right)/2;
    while(left<right)
    {
        mid=(left+right)/2;
        if(check(mid)!=0){left=mid+1;
        }
        else right=mid-1;
    }
    if(check(right))cout<<right;
     else cout<<right-1;
}

P1007 独木桥

本题难点在于 人转来转去 

实际上 人转来转去并不影响总时间 即可以看作两个人擦肩而过

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int l,n;
    cin>>l>>n;
    int a[n];
    for(int i=0;i<n;i++)
    {
        cin>>a[i];
    }
    int s[n],k[n];
    for(int i=0;i<n;i++)
    {
        s[i]=max(a[i]-0,l-a[i]+1);
        k[i]=min(a[i],l-a[i]+1);
    }
    int mx=0,minn=0;
    for(int i=0;i<n;i++)
    {
        if(s[i]>mx){mx=s[i];
        }
        if(k[i]>minn) minn=k[i]; 
    }
    cout<<minn<<" "<<mx;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值