Loading

noip模拟11

A. math

一个简单的找规律..考场上切了..

至此我们可以发现:很多数学题枚举找规律就能切切切切切

 

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define ll long long int
 4 #define lf double
 5 #define mp make_pair
 6 const ll N=1e6+50;
 7 inline void read(ll &ss)
 8 {
 9     ss=0; bool cit=0; char ch;
10     while(!isdigit(ch=getchar())) if(ch=='-') cit=1;
11     while(isdigit(ch)) ss=(ss<<3)+(ss<<1)+(ch^48),ch=getchar();
12     if(cit) ss=-ss;
13 }
14 ll n,mod,sum,cnt;
15 ll val[N];
16 ll gcd(ll a,ll b)
17 {
18     return b ? gcd(b,a%b) : a ;
19 }
20 signed main()
21 {
22 //    freopen("1.in","r",stdin);
23 //    freopen("out","w",stdout);
24     read(n); read(mod);
25     ll temp=mod;
26     for(ll i=1;i<=n;i++)
27     {
28         read(val[i]); val[i]%=mod;
29         temp=gcd(temp,val[i]);
30     }
31     printf("%lld\n",mod/temp);
32     for(ll i=0;i<mod;i+=temp)
33     {
34         printf("%lld ",i);
35     }
36     return 0;
37 }
38     
A_Code

 

LRX大佬在考场上打开测试数据之后发现:这道题的输出数据是一个等差数列..

于是 ta 打了一个随机化枚举到 850ms 直接切了..超大数据都卡不过.

所以这里再次安利随机化算法亦可玄学切切切..

B. biology

考场上打了一个记忆化搜索,但是这题卡的有点紧,但还是从 爆搜40pts -> 记忆化 60pts ..

正解是一个 O(nm) 的 dp..

#include<bits/stdc++.h>
using namespace std;
#define ll long long int
#define lf double
#define mp make_pair
const ll N=2e3+50;
inline void read(ll &ss)
{
    ss=0; bool cit=0; char ch;
    while(!isdigit(ch=getchar())) if(ch=='-') cit=1;
    while(isdigit(ch)) ss=(ss<<3)+(ss<<1)+(ch^48),ch=getchar();
    if(cit) ss=-ss;
}
ll n,m,alls,ans;
struct I { ll num,val,x,y; } a[N*N];
struct II { ll l,r; } b[N*N];
ll f[N][N],f1,f2,f3,f4;
inline bool comp(I aa,I bb)
{
    return aa.num==bb.num ? aa.val>bb.val : aa.num<bb.num ;
}
signed main()
{
    read(n); read(m);
    for(ll i=1;i<=n;i++)
    {
        for(ll j=1;j<=m;j++)
        {
            read(a[i*n-n+j].num);
            a[i*n-n+j].x=i; a[i*n-n+j].y=j;
        }
    }
    for(ll i=1;i<=n;i++)
    {
        for(ll j=1;j<=m;j++)
        {
            read(a[i*n-n+j].val);
        }
    }
    sort(a+1,a+1+n*m,comp);
    for(ll i=1;i<=n*m;i++)
    {
        if(a[i].num!=a[i-1].num)
        {
            b[alls].r=i-1;
            b[++alls].l=i;
        }
    }
    b[alls].r=n*m;
    for(ll i=b[1].l;i<=b[1].r;i++)
    {
        f1=max(f1,a[i].val+a[i].x+a[i].y);
        f2=max(f2,a[i].val+a[i].x-a[i].y);
        f3=max(f3,a[i].val-a[i].x+a[i].y);
        f4=max(f4,a[i].val-a[i].x-a[i].y);
    }
    ll maxn,maxn1,maxn2;
    for(ll i=2;i<=alls;i++)
    {
        for(ll j=b[i].l;j<=b[i].r;j++)
        {
            maxn1=max(f1-a[j].x-a[j].y,f2-a[j].x+a[j].y);
            maxn2=max(f3+a[j].x-a[j].y,f4+a[j].x+a[j].y);
            maxn=max(maxn1,maxn2); f[a[j].x][a[j].y]=maxn+a[j].val;
            ans=max(ans,f[a[j].x][a[j].y]);
        }
        for(ll j=b[i].l;j<=b[i].r;j++)
        {
            f1=max(f1,f[a[j].x][a[j].y]+a[j].x+a[j].y);
            f2=max(f2,f[a[j].x][a[j].y]+a[j].x-a[j].y);
            f3=max(f3,f[a[j].x][a[j].y]-a[j].x+a[j].y);
            f4=max(f4,f[a[j].x][a[j].y]-a[j].x-a[j].y);
        }
    }
    printf("%lld",ans);
    return 0;
}
/*
3 3
0 6 8
1 6 1
0 6 8
0 1 2
3 4 5
0 6 7

 */
B_Code

 

 

C. english

我们可以使用单调栈求出每个值作为最大值所覆盖的最大区间.

关于第一问,由于是求和,我们可以选择考虑二进制下每一位造成的贡献.

关于第二问,看到异或理应想到Trie树,发现这个是区间的最值,可以考虑可持久化.

#include<bits/stdc++.h>
using namespace std;
namespace BSS {
    #define ll long long int 
    #define ull unsigend ll
    #define re register ll 
    #define lf double
    #define lbt(x) (x&(-x))
    #define mp(x,y) make_pair(x,y)
    #define lb lower_bound 
    #define ub upper_bound
    #define File(x,y) freopen(#x,"r",stdin),freopen(#y,"w",stdout)
    #define Fill(x,y) memset(x,y,sizeof x)
    #define Copy(x,y) memcpy(x,y,sizeof x)
    inline ll read() {
        ll ss=0; bool cit=1; char ch;
        while(!isdigit(ch=getchar())) if(ch=='-') cit=0; 
        while(isdigit(ch)) ss=(ss<<3)+(ss<<1)+(ch^48),ch=getchar();
        return cit?ss:-ss;
    }
} using namespace BSS;

const ll N=1e5+51,mod=1e9+7;

ll m,n,tail,ans,tot,opt;
ll w[N],stk[N],cnt[N<<5],rt[N<<5],lst[N<<5];
ll tr[N<<5][2];
ll pre[N][20][2];
map<pair<ll,ll>,ll> map1;
struct I { ll l,r; } p[N];
inline void Work_One(){
    for(re i=1;i<=n;++i)
        for(re j=1;j<=20;++j)
            pre[i][j][1]+=pre[i-1][j][1]+((w[i]>>(j-1))&1),
            pre[i][j][0]+=pre[i-1][j][0]+(!((w[i]>>(j-1))&1));
    ans=0;
    for(re i=1;i<=n;++i){
        for(re j=1;j<=20;++j){
        (ans+=(1ll<<(j-1))*(pre[p[i].r][j][1]-pre[i-1][j][1])%mod*(pre[i][j][0]-pre[p[i].l-1][j][0])%mod*w[i]%mod)%=mod;
        (ans+=(1ll<<(j-1))*(pre[p[i].r][j][0]-pre[i-1][j][0])%mod*(pre[i][j][1]-pre[p[i].l-1][j][1])%mod*w[i]%mod)%=mod;
        }
    }
    printf("%lld\n",ans);
}
inline void ins(ll now,ll pre,ll val){
    ll p;
    for(ll i=20;~i;--i){
        tr[now][0]=tr[pre][0],tr[now][1]=tr[pre][1];
        p=(val>>(i-1))&1;
        tr[now][p]=++tot,
        now=tr[now][p],pre=tr[pre][p],
        cnt[now]=cnt[pre]+1;
    }
}
inline ll query(ll l,ll r,ll val,ll x){
    ll p,res=0,sum=0;
    for(ll i=20;~i;--i){
        p=(val>>(i-1))&1;
        if(cnt[tr[r][p^1]]>cnt[tr[l][p^1]]){
            if((res+(1ll<<(i-1)))>x) (sum+=cnt[tr[r][p^1]]-cnt[tr[l][p^1]])%=mod,r=tr[r][p],l=tr[l][p];
            else res=(res+(1ll<<(i-1)))%mod,r=tr[r][p^1],l=tr[l][p^1];
        }
        else r=tr[r][p],l=tr[l][p];
    }
    return sum;
}
inline void Work_Two(){
    ans=0; map1.clear();
    rt[0]=++tot,lst[tot]=-1;
    ins(rt[0],0,0);
    for(re i=1;i<=n;++i) ins((rt[i]=++tot),rt[i-1],w[i]);
    for(re i=1;i<=n;++i){
        if(i-p[i].l>p[i].r-i){
            for(re j=i;j<=p[i].r;++j){
                (ans+=(query(rt[p[i].l-1],rt[i],w[j],w[i])*w[i]))%=mod;
            }
        }
        else{
            for(re j=p[i].l;j<=i;++j){
                (ans+=(query(rt[i-1],rt[p[i].r],w[j],w[i])*w[i]))%=mod;
            }
        }
    }
    printf("%lld\n",ans);
}
inline void Work(){
    ll l,r,temp;
    for(re i=1;i<=n;i++)
        if(!tail){
            p[i].l=i,stk[++tail]=i;
        }
        else{
            if(w[stk[tail]]>w[i]) p[i].l=i,stk[++tail]=i;
            else{
                r=i-1,l=N;
                while(tail and w[stk[tail]]<=w[i]){
                    temp=stk[tail--],p[temp].r=i-1,
                    l=p[temp].l;
                }
                p[i].l=l,stk[++tail]=i;
            }
        }
    while(tail) temp=stk[tail--],p[temp].r=n;
    if(opt&1) Work_One(); if(opt&2) Work_Two(); 
}    
signed main(){
    n=read(),opt=read();
    for(re i=1;i<=n;i++) w[i]=read(); 
    Work();
    return 0;
}
C_Code

 

posted @ 2021-07-18 20:15  AaMuXiiiiii  阅读(20)  评论(0编辑  收藏  举报