hgoi#20190519

T1-求余问题

Abu Tahun很喜欢回文。
一个数组若是回文的,那么它从前往后读和从后往前读都是一样的,比如数组{1},{1,1,1},{1,2,1},{1,3,2,3,1}都是回文数组,但是数组{11,3,5,11},{1,12}不是回文的。
Abu Tahun有个包含n个整数的数组A,他想让它变成回文的。他可以任意选择一个整数m,然后让所有元素Ai变成Ai mod m。
求最大的m的值。

解法

显然,需要满足

a[1]===a[n](mod m)
a[2]===a[n-1](mod m)
......

则一定有最大的m为gcd(a[1]-a[n],a[2]-a[n-1],......)

ac代码

#include<bits/stdc++.h>
using namespace std;
int gcd(int a,int b){return b==0?a:gcd(b,a%b);}
int n,a[100010],ans=0;
int main()
{
    freopen("palindrome.in","r",stdin),freopen("palindrome.out","w",stdout);
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    for(int i=1;i<=n/2;i++)ans=gcd(ans,abs(a[i]-a[n-i+1]));
    if(ans)printf("%d\n",ans);else puts("-1");
    return 0;
}

T2-阶乘数组

你正在做“机器学习”研究,作为机器学习教育的一部分,你必须先学习组合数学。在老师给你讲了为什么组合数学里,到处会出现“阶乘!”后,你需要挑战下面这个问题:
给定一个数组\(A = [A_1,A_2,\dots,A_n]\),长度是n,你需要完成m次操作,操作有3种:
1、给定闭区间\([l, r]\),为区间内的所有数增加1
2、给定闭区间\([l, r]\),计算\(\sum_{i=l}^r A_i!\ mod\ 10^9\)
3、给位置i和数值v,将第i个数变成v

解法

因为是mod 1e9,所以40! mod 1e9就是0了
显然是个线段树,标算是对于线段树上的每一个节点,存一个数组,cnt[i]表示这一区间i的数量有多少个
这个做法的复杂度就是40*nlogn,虽然能过,但是代码很长,关键是我打炸了(大雾
还有一种做法,暴力维护,每次单点修是logn,查询是logn,区间修改暴力一下
有人会说:这不就n方了吗
所以需要优化,因为一个点最多进行40次区间修,所以维护一个标记,标记一个区间是否全部大于40
然后复杂度是一样的,但是连懒标记都不用打唉,还能爆踩标算有木有捏~(@^_^@)~

ac代码

#include<bits/stdc++.h>
#define mod 1000000000
#define ls (nw*2)
#define rs (nw*2+1)
#define mid ((l+r)>>1)
using namespace std;
int n,m,opt,x,y,g[40]={1},a[400010],t[400010],tag[400010];
void pushup(int nw){a[nw]=(a[ls]+a[rs])%mod,tag[nw]=tag[ls]&tag[rs];}
void build(int nw,int l,int r)
{
    if(l==r){scanf("%d",&t[nw]);if(t[nw]>=40)tag[nw]=1;else a[nw]=g[t[nw]];return;}
    build(ls,l,mid),build(rs,mid+1,r),pushup(nw);
}
void modify(int nw,int l,int r,int ql,int qr)
{
    if(tag[nw])return;
    if(l==r){t[nw]++;if(t[nw]>=40)a[nw]=0,tag[nw]=1;else a[nw]=g[t[nw]];return;}
    if(ql<=mid)modify(ls,l,mid,ql,qr);
    if(qr>mid)modify(rs,mid+1,r,ql,qr);
    pushup(nw);
}
void update(int nw,int l,int r,int q,int v)
{
    if(l==r){t[nw]=v;if(t[nw]>=40)a[nw]=0,tag[nw]=1;else a[nw]=g[t[nw]],tag[nw]=0;return;}
    if(q<=mid)update(ls,l,mid,q,v);else update(rs,mid+1,r,q,v);
    pushup(nw);
}
int query(int nw,int l,int r,int ql,int qr)
{
    if(ql<=l&&r<=qr)return a[nw];
    if(qr<=mid)return query(ls,l,mid,ql,qr);
    if(ql>mid)return query(rs,mid+1,r,ql,qr);
    return (query(ls,l,mid,ql,qr)+query(rs,mid+1,r,ql,qr))%mod;
}
int main()
{
    freopen("factorial.in","r",stdin),freopen("factorial.out","w",stdout);
    for(int i=1;i<=39;i++)g[i]=(1ll*g[i-1]*i)%mod;
    scanf("%d%d",&n,&m),build(1,1,n);
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d%d",&opt,&x,&y);
        if(opt==1)modify(1,1,n,x,y); 
        if(opt==2)printf("%d\n",query(1,1,n,x,y));
        if(opt==3)update(1,1,n,x,y);
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/muronglin/p/hgoi-20190519.html