11月05日解题报告

考试反思

这次考试翻了。。。明明是自己讲的数论,结果第一题居然没有看出来是费马小定理,第二题想到了用类似前缀和的方法,但因为时间问题没有继续想下去,匆匆打了个暴力,今天又是暴力的一天呐(两道题全tm暴力),还是要多多加油才行;

第一题

题面
给定 a 和 b,求 (…(( a^a)^a)^a …) a (b 个 a)。
AC思路
不难想到这个东西就是 a^a^(b-1) ,然后快速幂跑就好了。
注意一下取模, a^(p-1) 同余1(mod p) ,所以在计算 a^(b-1) 时,模 1e9+6。
O (log a+log b ) 。
代码

#include<iostream>
#include<cstdio>
using namespace std;
long long a;
long long b;
long long mod=1e9+7;
int main()
{
    cin>>a>>b;
    long long sum=1;
    long long l=a;
    long long ci=b-1;
    while(ci)
    {
        if(ci%2==1)sum=(sum*l)%(mod-1);
        l=(l*l)%(mod-1);
        ci=ci/2;
    }
    ci=sum;
    sum=1;
    l=a;
    while(ci)
    {
        if(ci%2==1)sum=(sum*l)%mod;
        l=(l*l)%mod;
        ci=ci/2;
    }
    cout<<sum;
}

第二题

题面
DYY 每天深夜套路健美。
DYY 有一个长度为 n 的健美序列,序列中每一个元素 1<=i<=n 都有一个权值 a i 。DYY 可以选取一个权值和为正奇数的连续区间[L,R](其中 1<=L<=R<=n),然后序列就会产生能量,让他变得更健美。
但是,如果序列能量过大,可能会吵醒住在隔壁的猫。
所以,DYY 希望你告诉他最小的权值和与区间的左右端点。若有多个区间符合条件,则按照左端点、右端点的顺序选择字典序最小的答案。若无解,DYY 也没有什么办法,只好输出-1 了。
AC思路
我们知道偶数减去比他小的奇数得到正奇数,奇数减去比他小的偶数得到正奇数,所以我们只要算一遍前缀和,然后把奇数和偶数分别存入两个set里面,对于每个数用lower_bound在另一个set中找大于等于它的数的位置,该位置-1的位置上的数就是比它小的最接近它的数了,然后更新和的最小值或者左右端点最小值就可以了;
代码

#include<iostream>
#include<cstdio>
#include<set>
using namespace std;
long long n;
long long    a[400000];
long long qian[400000];
long long l=0,r=0;
long long mm=41146456456464;
struct node
{
    long long zhi;
    long long id;
    friend bool operator < (node a,node b)
    {
        if(a.zhi<b.zhi)return 1;
        return 0;   
    }//定义运算符; 
};
set <node> q1,q2;
long long fabs(long long a)
{
    if(a<0)return -a;
    return a;
}//因为可能是负数所以要记得加绝对值; 
int main()
{
    scanf("%lld",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%lld",&a[i]);
        qian[i]=qian[i-1]+a[i];
    }
    node x;
    x.id=0,x.zhi=0,q2.insert(x);//预先存入一个0; 
    for(int i=1;i<=n;i++)
    {
        if(fabs(qian[i])%2==1)//如果是奇数 
        {
            x.zhi=qian[i];
            x.id=i;
            if(!q1.count(x))
                q1.insert(x);//如果队列中没有这个数才存入; 
            if(q2.empty())continue;//偶数队列中没值就略过; 
            set <node> ::iterator xx=q2.lower_bound(x);//找一个大于等于它的数的位置,那么其位置-1就是比它小的偶数; 
            set <node> ::iterator yy=q2.begin();//取开头; 
            if(xx==yy)continue;//如果大于等于它的就在队首,就说明前面没有数了,就略过; 
            --xx;//有数就取; 
            if(x.zhi-(*xx).zhi<mm&&x.zhi-(*xx).zhi>0)
            {
                mm=x.zhi-(*xx).zhi;
                l=(*xx).id+1;
                r=x.id;
            }//判断最小值,更新左右; 
            else if(x.zhi-(*xx).zhi==mm)
            {
                if((*xx).id+1<l)
                {
                    l=(*xx).id+1;
                    r=x.id; 
                }
            }//如果相等就找字典序最小的; 
        }
        else
        {
            x.zhi=qian[i];
            x.id=i;
            if(!q2.count(x))
                q2.insert(x);
            if(q1.empty())continue;
            set <node> ::iterator xx=q1.lower_bound(x);
            set <node> ::iterator yy=q1.begin(); 
            if(xx==yy)continue;
            --xx;
            if(x.zhi-(*xx).zhi<mm&&x.zhi-(*xx).zhi>0)
            {
                mm=x.zhi-(*xx).zhi;
                l=(*xx).id+1;
                r=x.id;
            }
            else if(x.zhi-(*xx).zhi==mm)
            {
                if((*xx).id+1<l)
                {
                    l=(*xx).id+1;
                    r=x.id; 
                }
            }
        }//和处理奇数的时候其实是一样的; 
    }
    cout<<mm<<" "<<l<<" "<<r<<endl;//输出; 
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值