2022“杭电杯”中国大学生算法设计超级联赛(2)(持续更新)

还是太菜了,一定抽时间把杭电能补的补完

目录

        1002 C++ to Python(签到)

1003 Copy

1007 Snatch Groceries(签到,四六级阅读题)

1009 ShuanQ(数学,思维)

1012 Luxury cruise ship(思维)


1002 C++ to Python(签到)

直接判断是否符合条件输出即可

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N =5e5+10,mod=998244353;
void solve()
{
    string s,s1="";
    cin>>s;
    for(int i=0;i<s.size();i++)
    {
        if((s[i]>='0'&&s[i]<='9')||s[i]=='('||s[i]==')'||s[i]==','||s[i]=='-')
            s1+=s[i];
    }
    cout<<s1<<"\n";
    return ;
}
signed main()
{
    int t;
    cin>>t;
    while(t--)
        solve();
    return 0;
}

1003 Copy

思路:首先明确一件事,题目要求我们求异或和.如果一个数字被选中偶数次,那么在最终的异或和的贡献就为0,而为奇数则对结果贡献为本身.只含有01状态,所以我们想到可以采用bitset来表示这个区间内的数字被选取的情况,选取偶数次就为0,奇数次为1,每一位对应当前位置的数字是否被选择.

然后就是对于题目中1,2操作的模拟.如果正向模拟会发现很难处理,这个时候如果把操作反着进行,会发现思路:

 每次我们对于某个位置进行2操作处理的话,那么这个位置的bitset值就会取反.如果是一操作的话,因为我们是倒着处理,那么完全可以把有原bitset中的r+1到N这一段进行向左(图中是向左,但是bitset相反)移动,直到r+1覆盖到 l 的位置,因为是倒着来的,所以我们后面的r+1到N其实是l到r这个区间后移得到的,那我们反着来前移就会返回上一步的状态,而且也不会影响结果,所以反着来模拟即可.我们把r+1到N和1到r这一段进行异或,为1的区间就表示这个点还是会被选中.

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
bitset<N>f,bef,now;
int a[N];
int op[N][3];
void solve()
{
    int n,m;
    f.reset();
    bef.reset();
    now.reset();
    cin>>n>>m;
    for(int i=1;i<=n;i++)
        cin>>a[i];
    for(int i=1;i<=m;i++)
    {
        cin>>op[i][0];
        if(op[i][0]==1)
            cin>>op[i][1]>>op[i][2];
        else
            cin>>op[i][1];
    }
    //已知取偶数次进行异或相当于没有取,所以想到bitset
    for(int i=m;i>=1;i--)
    {
        if(op[i][0]==1)
        {
            int l=op[i][1],r=op[i][2];
            bitset<N>temp;
            temp.set();
            bef=f&(temp>>(N-r-1));
            //取得0-r这一段
            temp.set();
            now=f&(temp<<(r+1));
            //取得r+1-n这一段
            f=bef^(now>>(r-l+1));
            //看移动后相交区域
        }
        else
        {
            int x=op[i][1];
            f[x]=!f[x];
        }
    }
    int res=0;
    for(int i=1;i<=n;i++)
        if(f[i])
            res^=a[i];
        cout<<res<<endl;
    return ;
}
signed main()
{
    cin.tie(0);
    cout.tie(0);
    ios::sync_with_stdio(0);
    int t;
    cin>>t;
    while(t--)
       solve();
    return 0;
}

1007 Snatch Groceries(签到,四六级阅读题)

直接判断哪些线段没有和其他线段相交即可

#include <iostream>
#include <algorithm>
using namespace std;
const int N = 1e5 + 10;
struct edge
{
    int l,r;
    bool operator < (const edge & A)const{
        if(l == A.l) return r < A.r;
        return l < A.l;
    }
}e[N];
void solve()
{
    int n;   
    scanf("%d",&n);

    int ans = 0;
    for(int i=1;i<=n;i++) 
    {
        scanf("%d%d",&e[i].l,&e[i].r);
    }
    sort(e+1,e+1+n);
    for(int i=1;i<=n;i++)
    {   
        if((i + 1 <= n && e[i + 1].l > e[i].r) || i == n)ans ++;
        else break;
    }
    printf("%d\n",ans);
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)solve();
    return 0;
}

1009 ShuanQ(数学,思维)

思路:我们可以把式子转化一下变为:

P*Q-1=k*m

由此可以知道m是p*q-1的一个质因子,又因为要满足m>=p且m>=q.所以我们直接用质因数分解来求出p*q-1的最大质因子,这个就是m的值,再check一下m和p,q的值即可

#include<bits/stdc++.h>
#define int long long 
using namespace std;
void solve()
{
    int p,q,en;
    cin>>p>>q>>en;
    int m=p*q-1;
    for(int i=2;i*i<=m;i++)
        while(m%i==0)
            m/=i;
    if(m<q||m<p)
        cout<<"shuanQ"<<endl;
    else
    {
        int ans=en*q%m;
        cout<<ans<<endl;
    }
    return ;
}
signed main()
{
    cin.tie(0);
    cout.tie(0);
    ios::sync_with_stdio(0);
    int t;
    cin>>t;
    while(t--)
       solve();
    return 0;
}

1012 Luxury cruise ship(思维)

思路:去年好像在cf上做过类似的题.我们先求出7,31,365的最小公倍数,因为三者互质,直接相乘即可.然后用n%lcm,整除lcm的部分我们用贪心去算,因为是7,31,365的公倍数,所以我们直接全部用365装就是最优解.然后剩下的部分也不大,直接三层for循环跑一下就行了(背包也可以,反正剩下部分不大,直接瞎搞)

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N =5e5+10,mod=998244353;
void solve()
{
    int n,lcm=7*31*365;
    cin>>n;
    if(n>=lcm)
    {
        int temp=n/lcm;
        n%=lcm;
        int ans=1e18;
        for(int i=0;i*365<=n;i++)
        {
            for(int j=0;j*31<=n;j++)
            {
                if(n-i*365-j*31<0)
                    break;
                if((n-i*365-j*31)%7==0)
                {
                    ans=min(ans,i+j+(n-i*365-j*31)/7);
                }
            }
        }
        if(ans==1e18)
        {
            cout<<"-1\n";
        }
        else
        {
            ans+=temp*7*31;
            cout<<ans<<"\n";
        }
    }
    else
    {
        int ans=1e18;
        for(int i=0;i*365<=n;i++)
        {
            for(int j=0;j*31<=n;j++)
            {
                if(n-i*365-j*31<0)
                    break;
                if((n-i*365-j*31)%7==0)
                {
                    ans=min(ans,i+j+(n-i*365-j*31)/7);
                }
            }
        }
        if(ans==1e18)
        {
            cout<<"-1\n";
        }
        else
        {
            cout<<ans<<"\n";   
        }
    }
    return ;
}
signed main()
{
    int t;
    cin>>t;
    while(t--)
       solve();
    return 0;
}
//genius

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值