22CCPC威海+思维

本文探讨了编程竞赛中的重要策略和算法应用。第一部分介绍了如何在面对复杂问题时保持冷静,强调了清晰思考和避免无谓担忧的重要性。第二部分涉及代码实现,讲解了一种解决特定问题的算法思路。第三部分讨论了线性几何问题的解决方案,通过巧妙的数学方法快速判断点共线。第四部分展示了如何通过二分查找和贪心策略解决字符串异或问题。最后,文章还涉及到了资源分配问题的动态规划解法。
摘要由CSDN通过智能技术生成

尽快调整回来,这可能是你人生最重要的一年,好好审视自己,拎得清一点,丢弃掉无谓的担心,清楚自己在做什么。
既然大二有能力去做好一些事,那么大三就更没必要畏首畏尾,认真做好每一件事,还是那句话,把握好你能掌控住的东西,脚踏实地得努力实现。只要愿意去做,就一定能做好,待人可以平和,但是心气不能掉,懒惰会毁掉一个人。
再做不到,直接remake去吧


J. Eat, Sleep, Repeat

思路还算简单,只有出现次数从0开始连续向上的数,才会卡住一些数让他们不能递减。
代码我敲的很卡,不知道怎么写好。
代码思路:
1.使用map存下所有的限制条件,单独筛选出出现次数为0的数字存到数组中记为id。
2.对于数组a和数组id都进行降序排列。对数组id进行循环,为每个数组a中数字找到下界。
3.对数组a进行循环,不断向上取,每一个数有mp进行数量限制。

#include <bits/stdc++.h>
#define endl '\n'
#define int long long
#define ios (ios::sync_with_stdio(false),cin.tie(0),cout.tie(0))
#define PII pair<int,int>

using namespace std;
const int N =7e5+5;
const int inf=1e18;
const int mod=998244353;
const double eps=1e-8;
int n,k,m,a[N],id[N],vis[N];
struct node
{
    int val,cnt;
}e[N];
bool cmp(int a,int b){return a>b;}
map<int,int>mp;
void solve()
{
    cin>>n>>k;
    for(int i=1;i<=n;i++) cin>>a[i];
    for(int i=0;i<=n;i++) id[i]=vis[i]=0;
    mp.clear();
    m=0;
    for(int i=1;i<=k;i++)
    {
        cin>>e[i].val>>e[i].cnt;
        mp[e[i].val]=e[i].cnt;
        if(e[i].cnt==0) id[++m]=e[i].val;
    }
    sort(a+1,a+n+1,cmp);
    sort(id+1,id+m+1,cmp);
    for(int i=1,j=1;i<=m;i++)
    {
        while(id[i]>a[j]&&i<=m) i++;
        if(i>m) break;
        while(id[i]<a[j]) vis[j]=id[i]+1,j++;
    }
    int y=0,ans=0;
    for(int i=1;i<=n;i++)
    {
        if(vis[i])
        {
            int x=vis[i];
            while(mp.count(x)&&mp[x]<=0) x++;
            ans+=a[i]-x;
            if(mp.count(x)) mp[x]--;
        }
        else
        {
            while(mp.count(y)&&mp[y]<=0) y++;
            ans+=a[i]-y;
            if(mp.count(y)) mp[y]--;
        }
    }
    if(ans&1) cout<<"Pico"<<endl;
    else cout<<"FuuFuu"<<endl;
}
signed main()
{
    //ios;
    int T;cin>>T;
    while(T--)
        solve();
    return 0;
}

C. Grass

首先要想到一块草坪若5个点共线肯定不存在,否则就能找到一块符合条件的草坪。因此我们只要固定四个点,去找不共线的第五个点。
对于5个点的判断:方法很多,都很难敲,看到个很巧妙的方法。用set集合,使用最大公约数化成最简形式,观察数量。比我想的一堆垃圾方法好多了。。。

#include <bits/stdc++.h>
#define endl '\n'
#define int long long
#define ios (ios::sync_with_stdio(false),cin.tie(0),cout.tie(0))
#define PII pair<int,int>

using namespace std;
const int N =3e4+5;
const int inf=1e18;
const int mod=998244353;
const double eps=1e-8;
int n;
struct Point
{
    int x,y;
}p[N],P[6];
bool check()
{
    for(int i=1;i<=5;i++)
    {
        set<pair<int,int>>s;
        for(int j=1;j<=5;j++)
        {
            if(j!=i)
            {
                int x=p[i].x-p[j].x,y=p[i].y-p[j].y;
                int tmp=__gcd(x,y);
                tmp=abs(tmp);
                s.insert({x/tmp,y/tmp});
            }
        }
        if(s.size()==4)
        {
            P[1]={p[i].x,p[i].y};
            int g=1;
            for(int j=1;j<=5;j++)
            if(j!=i) P[++g]={p[j].x,p[j].y};
            return 1;
        }
    }
    return 0;
}
void solve()
{
    cin>>n;
    for(int i=1;i<=n;i++) cin>>p[i].x>>p[i].y;
    int flag=0;
    if(n<5)
    {
        cout<<"NO"<<endl;return;
    }
    for(int i=5;i<=n;i++)
    {
        swap(p[i],p[5]);
        if(check())
        {
            flag=1;break;
        }
    }
    if(flag)
    {
        cout<<"YES"<<endl;
        for(int i=1;i<=5;i++)
            cout<<P[i].x<<" "<<P[i].y<<endl;
    }
    else
        cout<<"NO"<<endl;

}
signed main()
{
    //ios;
    int T;cin>>T;
    while(T--)
        solve();
    return 0;
}

C. Complementary XOR

在题数没积累到一定量时,一眼是看不出来的,需要安静下来去分析,浮躁很难做出题来。
思路:
1.如果两个字符串的相同位置既存在值相同的情况,也存在值不同的情况,那么肯定是无解的。
eg: 0 1
—- 1 1
总会存在一个消不去的1。
2.将s1中的1全部化为0,需要g次。若g为偶数,则满足题意;若g为奇数,在最后一个1划掉后,s2全部变为1,进行如下三次操作:对s1的1~n进行翻转,再对1 ~1、2 ~n进行翻转。

#include <bits/stdc++.h>
#define endl '\n'
#define int long long
#define ios (ios::sync_with_stdio(false),cin.tie(0),cout.tie(0))
#define PII pair<int,int>

using namespace std;
const int N =1e6+5;
const int inf=1e18;
const int mod=998244353;
int n;
string s1,s2;
void solve()
{
    cin>>n>>s1>>s2;
    s1=" "+s1;s2=" "+s2;
    int f1=0,f2=0;
    for(int i=1;i<=n;i++)
    {
        if(s1[i]==s2[i]) f1=1;  //各个位置相同
        else f2=1;              //各个位置不同
    }
    if(f1&&f2)
    {
        cout<<"No"<<endl;return;
    }
    cout<<"Yes"<<endl;
    vector<pair<int,int>>e;
    int ans=0,g=0;
    if(!f1&&f2)
    {
        ans++;e.push_back({1,n});
        for(int i=1;i<=n;i++) s1[i]^=1;
    }
    for(int i=1;i<=n;i++)
        if(s1[i]=='1') ans++,g++,e.push_back({i,i});
    if(g%2)
        ans+=3,e.push_back({1,n}),e.push_back({1,1}),e.push_back({2,n});
    cout<<ans<<endl;
    for(auto x:e)
        cout<<x.first<<" "<<x.second<<endl;
}
signed main()
{
    //ios;
    int T;cin>>T;
    while(T--)
        solve();
    return 0;
}

I. Dragon Bloodline

详细注释在代码中,实在是难写。。。。好菜啊好菜

#include <bits/stdc++.h>
#define endl '\n'
#define int long long
#define ios (ios::sync_with_stdio(false),cin.tie(0),cout.tie(0))
#define PII pair<int,int>

using namespace std;
const int N =7e5+5;
const int inf=1e18;
const int mod=998244353;
const double eps=1e-8;
int n,k,a[N],b[105],c[105],f[N],suma=0,sumb=0,sum=0,d[N];
bool check(int x)   //二分蛋的数量
{
    int kk=0,g=x;
    for(int i=1;i<=n;i++)
    {
        d[i]=a[i]*x;    //每种物质需要数量
        kk+=d[i];
        if(kk>sum) return 0;
    }
    for(int i=1;i<=k;i++) f[i]=b[i];  //工作的龙数量
    for(int i=k;i>=1;i--)
    {
        sort(d+1,d+n+1);    //物质排序、贪心
        for(int j=n;j>=1&&f[i]&&d[j];j--)
        {
            int tmp=d[j]/c[i];  //需要的龙
            if(tmp>f[i])
            {
                d[j]-=c[i]*f[i];f[i]=0;
            }
            else
            {
                d[j]-=c[i]*tmp;f[i]-=tmp;
            }
        }
        sort(d+1,d+n+1);
        for(int j=n;f[i];j--)
        {
            if(d[j])
            {
                d[j]=0;f[i]--;
            }
            else return 1;
        }
    }
    for(int i=1;i<=n;i++)
        if(d[i]) return 0;
    return 1;
}
void solve()
{
    suma=0,sumb=0,sum=0;
    cin>>n>>k;
    for(int i=1;i<=n;i++) cin>>a[i],suma+=a[i]; //需要的物质
    sort(a+1,a+n+1);
    for(int i=1;i<=k;i++)   //工作龙
    {
        cin>>b[i];
        sumb+=b[i];
        if(i==1) c[i]=1,sum+=c[i]*b[i];
        else c[i]=c[i-1]*2,sum+=c[i]*b[i];
    }
    int l=0,r=sum/suma,mid,ans;
    while(l<=r)
    {
        mid=(l+r)>>1;
        if(check(mid)) l=mid+1,ans=mid;
        else r=mid-1;
    }
    cout<<ans<<endl;
}
signed main()
{
    ios;
    int T;
    cin>>T;
    while(T--)
        solve();
    return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值