集训考试【更新完成】

28的因子

首先,必须保证7个个数达到最大,4的个数最少,才能做到数最小,因此可以先找出7的最大个数,然后依次递减循环,找符合答案的数即可
另外,思维不要固定,不一定输出多位数就必须只是输出这个数,也可以通过循环一位一位地输出每一位数达到目的!!!

#include <bits/stdc++.h>
using namespace std;

int main()
{
    int n,x,y;
    while(scanf("%d",&n)!=EOF)
    {
        int flag=0;
        int t=n/7;//记录7的个数,以此进行下一步循环,以保证7的个数最多,4最少,使数最小//
        for(int i=t;i>=0;i--)//7的个数可能为0//
        {
            if((n-7*i)%4==0)
            {
                flag=1;
                y=i;
                x=(n-7*i)/4;
                break;
            }
        }
        if(flag==0)
            printf("xinganheixiong\n");
        else
        {
            for(int i=1;i<=x;i++)
            {
                printf("4");
            }
            for(int i=1;i<=y;i++)
            {
                printf("7");
            }
            printf("\n");
        }
    }

    //cout << "Hello world!" << endl;
    return 0;
}

陈老师发奖金

结构体排序,不过要注意有一个条件是有关读入顺序的,因此结构体内需要一个量来记录读入顺序!!!

#include <bits/stdc++.h>
using namespace std;

struct student
{
    int name,c,ying,gao,xu;
    int sum;
}stu[1000000];
bool cmp(student a,student b)
{
    if(a.sum!=b.sum)
    {
        return a.sum>b.sum;
    }
    if(a.sum==b.sum&&a.ying!=b.ying)
    {
        return a.ying>b.ying;
    }
    if(a.sum==b.sum&&a.ying==b.ying)
    {
        return a.xu>b.xu;
    }
}
int main()
{
    ios::sync_with_stdio(false);
    int n;
    while(cin>>n)
    {
        for(int i=0;i<n;i++)
        {
            cin>>stu[i].name>>stu[i].c>>stu[i].ying>>stu[i].gao;
            stu[i].sum=stu[i].c+stu[i].gao;
            stu[i].xu=i+1;
        }
        sort(stu,stu+n,cmp);
        if(n<=4)
        {
            for(int i=0;i<n;i++)
            {
                printf("%d %d\n",stu[i].name,stu[i].sum);
            }
        }
        else
        {
            for(int i=0;i<4;i++)
            {
                printf("%d %d\n",stu[i].name,stu[i].sum);
            }
        }
    }
    //cout << "Hello world!" << endl;
    return 0;
}

小明分蛋糕

通过连续的除和模即可求得结果
注意蛋糕数不能为负,但是在分蛋糕的过程中可以超过需要的数量!!!

#include <bits/stdc++.h>
using namespace std;
int main()
{
    int t,count,count1,count2;
    long long a,b;
    cin>>t;
    while(t--)
    {
        cin>>a>>b;
        long long x=b-a;
        long long y;
        if(x<0)
        {
            count=(-x)/5+(-x)%5/2+(-x)%5%2;
        }
        if(x>0)
        {
            count1=x/5+x%5/2+x%5%2;
                count2=x/5+1;
                y=count2*5;
                count2=count2+(y-x)/2+(y-x)%2;
                if(count1<count2)
                    count=count1;
                else
                    count=count2;
        }
        cout<<count<<endl;
    }
    //cout << "Hello world!" << endl;
    return 0;
}

神奇的事情发生了

栈!!!
根据题意要求,合理利用栈的特点

#include <bits/stdc++.h>
using namespace std;

const int N=1e5;
char ch[N];
stack<char>x1;
stack<char>x2;
int main()
{
    while(scanf("%s",ch)!=EOF)
    {
        int len=strlen(ch);
        for(int i=0;i<len;i++)
        {
            if(x1.empty())
            {
                x1.push(ch[i]);
                continue;
            }
            if(ch[i]=='O')
            {
                char k=x1.top();
                if(k=='O') x1.pop();
                else
                    x1.push(ch[i]);
            }
            else if(ch[i]=='o')
            {
                char k=x1.top();
                if(k=='o')
                {
                    x1.pop();
                    if(x1.empty()) x1.push('O');
                    else
                    {
                        k=x1.top();
                        if(k=='O') x1.pop();
                        else x1.push('O');
                    }
                }
                else x1.push(ch[i]);
            }
        }
        while(!x1.empty())
        {
            x2.push(x1.top());
            x1.pop();
        }
        while(!x2.empty())
        {
            printf("%c",x2.top());
            x2.pop();
        }
        printf("\n");
    }
    //cout << "Hello world!" << endl;
    return 0;
}

jwMM的射箭游戏

根据题意即可得出,x2-y2的结果与x1和y1的最大公约数有不为1的公约数即可,但是要注意,x2-y2的结果可能不大于0,此时直接输出N!!!

#include <bits/stdc++.h>
using namespace std;
int gcd(int a,int b)
{
    return b==0?a:gcd(b,a%b);
}
int main()
{
    int x1,y1,x2,y2;
    while(scanf("%d%d%d%d",&x1,&y1,&x2,&y2)!=EOF)
    {
        int x=x2-y2;
        int y=gcd(x1,y1);
        if(x>0&&gcd(x,y)==1||x<=0)
            printf("N\n");
        else
            printf("Y\n");
    }
    return 0;
}

抹发胶

#include <bits/stdc++.h>
using namespace std;

int main()
{
    int t,n,x[110],count;
    while(scanf("%d",&t)!=EOF)
    {
        while(t--)
        {
            scanf("%d",&n);
        for(int i=0;i<n;i++)
            scanf("%d",&x[i]);
            for(int i=0;i<n-1;i++)
            {
                count=0;
                for(int j=0;j<i;j++)
                {
                    if(x[j]<x[i])
                        count++;
                }
                printf("%d ",count);
            }
            count=0;
            for(int j=0;j<n-1;j++)
            {
                if(x[j]<x[n-1])
                    count++;
            }
            printf("%d\n",count);
        }
    }
    //cout << "Hello world!" << endl;
    return 0;
}

吃辣条

#include <bits/stdc++.h>
using namespace std;

int main()
{
    ios::sync_with_stdio(false);
    int n,a[110];
    while(cin>>n)
    {
        for(int i=0;i<n;i++)
            cin>>a[i];
        sort(a,a+n);
        printf("%d %d\n",a[n-2],a[1]);
    }
    //cout << "Hello world!" << endl;
    return 0;
} 

天哥的难题

当只有1位二进制的时候即题目中的m为1的时候,a+b=a|b答案有(0,0) (0,1) (1,0)所以根据这一位可以推出后面的情况 因为每一位都有三种情况 所以你在m等于1的时候得出的三个答案每一个前面都可以加上(0,0) (0,1) (1,0) 也就是(0,0)->(00,00) (10,00) (00,10) (0,1)->(00,01) (10,01) (00,11) (1,0)->(01,00) (11,00) (01,10) 所以后面每多加一位的话方案数就会乘3,所以就可以上快速幂了。

#include <bits/stdc++.h>
using namespace std;
const long long mod=1e9+7;
long long quickmod(long long a,long long b)
{
    long long sum=1;
    while(b)
    {
        if(b&1)
        {
            sum=sum*a%mod;
        }
        a=a*a%mod;
        b>>=1;
    }
    return sum;
}
int main()
{
    long long n,ans;
    ios::sync_with_stdio(false);
    while(cin>>n)
    {
        ans=quickmod(3,n);
        cout<<ans<<endl;
        //printf("%lld\n",ans);
    }
    //cout << "Hello world!" << endl;
    return 0;
}

丹青玩游戏

思路:本题应用二进制枚举!根据题意,当与相应灯泡有关的开关为“on”的数量对2取模的结果与p相同时,灯泡才会亮,但是这时其余无关的开关是“on”还是“off“都有可能,因此情况有多种。

#include <bits/stdc++.h>
using namespace std;
struct node//结构体记录与灯泡相关的开关数量,编号还有开灯状态//
{
    int k;
    int a[15];
    int p;
}s[15];
int main()
{
    int n,m;
    int i,j,k;
    int b[15],num,flag,ans;//b数组为临时数组,记录每种情况下标记为"on"的开关,num记录灯泡相关的开关为“on”的数量,ans记录符合条件的方案数量//
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        ans=0;
        for(i=0;i<m;i++)
        {
            scanf("%d",&s[i].k);
            for(j=0;j<s[i].k;j++)
                scanf("%d",&s[i].a[j]);
        }
        for(i=0;i<m;i++)
            scanf("%d",&s[i].p);
        for(i=0;i<(1<<n);i++)//枚举过程
        {
            flag=0;
            memset(b,0,sizeof(b));
            for(j=0;j<n;j++)
            {
                if(i&(1<<j))//标记所有为开的开关
                {
                    b[j+1]=1;
                }
            }
            for(j=0;j<m;j++)//检验是否符合条件
            {
                num=0;
                for(k=0;k<s[j].k;k++)
                    if(b[s[j].a[k]]==1)num++;
                if(num%2!=s[j].p)
                {
                    flag=1;
                    break;
                }
            }
            if(flag==0)ans++;
        }
        printf("%d\n",ans);//输出
    }
    return 0;
}

分糖果

考察的是二分查找,但是可以用lower_bound简化二分的部分

思路:第一步先对写入的数据直接取模(写入时就取模,因为原数据其实是不需要的);第二步对数据从小到大进行排序;第三步开始循环,具体步骤如下: 从头开始循环,每层循环中,利用lower_bound找出第一个大于等于m-a[i]的下标k,那么k的前一个数就可能是满足条件的,但是这个可能是i本身,这时候要再找它前一个数就是满足条件的了,但要注意的是,这两种情况都必须保证数组不能越界(具体看代码部分),还需要注意得是如果目标数不是恰好的m-a[i],就有可能不是最大的,需要再进行一步比较,即与(a[i]+a[n-1])%m比较,当然这也得再i不是n-1的情况下,综上情况找出的值就是答案了

#include <bits/stdc++.h>
using namespace std;

int t,n,m,ans,k;
int a[1000000];
int main()
{
    ios::sync_with_stdio(false);
    cin>>t;
    while(t--)
    {
        cin>>n>>m;
        for(int i=0;i<n;i++)
        {
            cin>>a[i];
            a[i]%=m;//直接取模
        }
        sort(a,a+n);//排序
        ans=0;
        for(int i=0;i<n;i++)
        {
            k=lower_bound(a,a+n,m-a[i])-a;
            if(k-1>=0)//保证数组不越界
            {
                if(k-1!=i)//如果前一个数不是i,就直接与这个数相加
                {
                    k--;
                    ans=max(ans,a[i]+a[k]);
                }
                else if(k-2>=0)//如果前一个数就是i本身,在保证数组不越界的情况下就找再前一位得数即可
                {
                    k-=2;
                    ans=max(ans,a[i]+a[k]);
                }
            }
            if(i!=n-1)//最后的一步比较,有可能上面找到的不是恰好的m-a[i]所以有了这一步
                ans=max(ans,(a[i]+a[n-1])%m);
        }
        printf("%d\n",ans);
    }
    return 0;
}

jwMM选酒店

思路:根据题意,先假设姐妹中随便一个人住在i酒店(随便谁都好,对结果无影响,因为本题不考虑两人的排列),如果该酒店可以喝奶茶,就记录从开始到该酒店所有与该酒店颜色相同的酒店数;如果该酒店不能喝奶茶,那么就是从开始到距离该酒店左侧最近的可以喝奶茶的店铺位置所有与i酒店颜色相同的酒店数(至于为什么是距离最近的?原因是:如果姐妹住的酒店固定,那么无论在哪里喝奶茶,都属于一种方案,所以选择距离最近的),此时所记录的酒店数就是该种情况下的方案数,以此方式进行循环,把每次循环的方案数相加,最后就是结果

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2e5+1;
int color[maxn];//每个酒店的颜色
int num[60];//下标是酒店颜色,记录的是从头开始到每次循环的i酒店(能喝奶茶的情况下,如果不能就是到距离i最近的能奶茶的酒店)位置,的与i酒店颜色相同的酒店数量,(每次循环可能会更新)
int main()
{
    int n,m,pp,t;//t当次循环的酒店如果可以喝奶茶就记录,以助于下一次循环对num[]的更新
    cin>>n>>m>>pp;
    t=0;
    ll sum=0;
    for(int i=1;i<=n;i++)
    {
        int c,wi;
        cin>>c>>wi;
        color[i]=c;
        if(wi<=pp)
        {
            for(int j=t+1;j<=i;j++)//t及其以前的酒店颜色已经被记录过了,所以从t+1开始
                num[color[j]]++;
            t=i;
            sum+=num[c]-1;//方案数不能加上i酒店
        }
        else
            sum+=num[c];
    }
    cout<<sum<<endl;
    return 0;
}

煊哥的数字游戏

搬运

思路:可以设
sum=a1+a2+…+am
num=a1⊕a2⊕…⊕am
这样这道题就成了找出一个整数 t 使得 sum+t=num⊕2t
若要使最后sum=num ,只需要将sum与num二进制中各个位置上对应相等

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int a[200010];
int n,x;
ll sum,num,y,ans;
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
        sum+=a[i];
        num^=a[i];
    }
    ans=sum;//记录原来的sum值
    num*=2;//因为是两倍关系 所以要乘2
    while(sum!=num)//sum与num不相等就需要继续进行
    {
        x++;
        y=(ll)pow(2,x);
        if(sum%y!=num%y)//二进制的末位开始判断
        {
            sum+=y/2;
            num^=y;
        }
    }
    if(x>0)//若一开始sum就与num相等那么直接输出0
        printf("%lld\n",sum-ans);
    else printf("0\n");
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值