E题
经过思考后发现a只有递增的时候条件才会有用,所以我们创建数组时只需要把递增的a加进去就可以,然后思考一开始的n的取值有【n*b,(n+1)*b-1】这个区间内,然后我们就可以区间取交集,把这些符合n的区间加起来。
using Pll=pair<ll,ll>;
int x;
ll n;
vector<Pll> v;
ll a[MAXN];
ll b[MAXN];
ll query(ll l,ll r,ll x){
ll tmp1=x*n,tmp2=(n+1)*x-1;
l=max(l,tmp1);
r=min(r,tmp2);
return max(0ll,r-l+1);
}
void solve(){
scanf("%d",&x);
int mx=0;
for(int i=1;i<=x;i++){
scanf("%lld %lld",a+i,b+i);
if(a[i]>mx){
mx=a[i];
v.push_back(Pll(a[i],b[i]));
}
}
scanf("%lld",&n);
if(n>=mx) return void(printf("1"));
ll ans=0;
for(int i=0;i<v.size();i++){
if(i) ans+=query(v[i-1].first,v[i].first-1,v[i].second);
else ans+=query(1,v[i].first-1,v[i].second);
}
printf("%lld",ans);
}
F题
要求所以子区间的平均数和,可以思考得出一个规律
其他的情况同理,所以可以直接写代码了,注意要求个逆元就行
const int mod=1e9+7;
int n;
ll a[MAXN];
ll pre[MAXN];
ll sum[MAXN];
ll q_pow(ll a,ll b){
ll rec=1;
while(b){
if(b&1){
rec=rec*a%mod;
}
b>>=1;
a=a*a%mod;
}
return rec;
}
void solve(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%lld",a+i);
pre[i]=(a[i]+pre[i-1])%mod;
}
for(int i=1;i<=n;i++){
if(i<=n/2+n%2){
sum[i]=(sum[i-1]+pre[n-i+1]-pre[i-1])%mod;
}else{
sum[i]=sum[n-i+1];
}
}
ll ans=0;
for(int i=1;i<=n;i++){
ans+=sum[i]*q_pow(i,mod-2);
ans%=mod;
}
printf("%lld\n",ans);
}
G题
刚好最近在学字符串哈希它就来了,直接正序倒序求哈希,然后开始枚举删除的后缀长度,前缀那一段就只有1,本来就是回文串2.差一个是回文串3.差很多个是 就这三种分别判断一下就行,其中还要区分奇偶串,特判一下就OK,判断是否为差一个为回文串可以利用二分求最大回文子串,然后到达那个不是的字符时再判断其剩下两边的串是否为回文即可说明他是否是差一个为回文串。
int n;
char s[MAXN];
ull h1[MAXN];
ull h2[MAXN];
ull g[MAXN];
const int p=131;
ull query1(int l,int r){
return h1[r]-h1[l-1]*g[r-l+1];
}
ull query2(int l,int r){
return h2[l]-h2[r+1]*g[r-l+1];
}
void solve(){
scanf("%d",&n);
scanf("%s",s+1);
g[0]=1;
for(int i=1;i<=n;i++){
g[i]=g[i-1]*p;
h1[i]=h1[i-1]*p+(ull)s[i];
}
int ans=0;
for(int i=n;i>=1;i--) h2[i]=h2[i+1]*p+(ull)s[i];
for(int i=0;i<n;i++){
int tmp=(n-i)/2+(n-i)%2;
if((n-i)%2){
if(query1(1,n-i)==query2(1,n-i)) ans+=26;
else{
int l=0,r=tmp-1;
while(l<=r){
int mid=l+r>>1;
if(query1(tmp-mid,tmp-1)==query2(tmp+1,tmp+mid)) l=mid+1;
else r=mid-1;
}
if(query1(1,tmp-l-1)==query2(tmp+l+1,n-i)) ans+=2;
}
}else{
if(query1(1,n-i)==query2(1,n-i)) ans+=1;
else{
int l=0,r=tmp;
while(l<=r){
int mid=l+r>>1;
if(query1(tmp-mid+1,tmp)==query2(tmp+1,tmp+mid)) l=mid+1;
else r=mid-1;
}
if(query1(1,tmp-l)==query2(tmp+l+1,n-i)) ans+=2;
}
}
}
printf("%d",ans);
}
个人认为这套题出的还是很好的