考试反思
这次考试翻了。。。明明是自己讲的数论,结果第一题居然没有看出来是费马小定理,第二题想到了用类似前缀和的方法,但因为时间问题没有继续想下去,匆匆打了个暴力,今天又是暴力的一天呐(两道题全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;//输出;
}