简单的题目 专题

挖坑

总是要填的

可是我不填

哎呀真香!

水题1

 既然是简单的题目,那当然是放大水题辣

只有a,b  的二进制的每一个1位置都不同时a&b ==0 

 所以随便维护一下每个数二进制有1位的序列最大值就行了QAQ

#include <iostream>
#include <cstdio>
using namespace std;
const int N=100000+10;
int a[N],dp[N],s[60],ans,n;
 
void read(int &x){
    x=0;int f=1;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')f=-f;c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    x*=f;
}
 
int main(){
    read(n);
    for(int i=1;i<=n;i++) read(a[i]);
    for(int i=1;i<=n;i++){
        int x=a[i],mx=0,t=0;
        while(x){
            ++t;
            if(x%2) mx=max(mx,s[t]);
            x/=2;
        }
        dp[i]=mx+1;
        x=a[i];t=0;
        while(x){
            ++t;
            if(x%2) s[t]=max(s[t],dp[i]);
            x/=2;
        }
        ans=max(ans,dp[i]);
    }
    printf("%d",ans);
    return 0;
}
View Code

水题2 

 既然是简单的题目,那当然是放大水题辣

正反hash,暴力枚举串o1判断

剪枝:ans*k如果大于n,显然不比当前答案更优

#include <iostream>
#include <cstdio>
#include <map>
#define ull unsigned long long
using namespace std;
const int base=19260817;
const int N=200000+10;
int n,a[N];
ull b[N],hs1[N],hs2[N];
map<ull,bool>mp;
//set<ull>se;

void read(int &x){
    x=0;int f=1;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')f=-f;c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    x*=f;
}

void read(ull &x){
    x=0;ull f=1;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')f=-f;c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    x*=f;
}

int st[N],top;
int main(){
    read(n);
    for(register int i=1;i<=n;i++) read(a[i]);
    b[0]=1;
    for(register int i=1;i<=n;i++) b[i]=b[i-1]*base;
    for(register int i=1;i<=n;i++) hs1[i]=hs1[i-1]*base+a[i];
    for(register int i=n;i;i--) hs2[i]=hs2[i+1]*base+a[i];
    int ans=0;
    for(register int i=1;i<=n;i++){
        int s=0;
        mp.clear();
        ull h,f;
        for(register int j=i;j<=n;j+=i){
            if(ans*i>n) break;
            h=hs1[j]-hs1[j-i]*b[i];
            f=hs2[j-i+1]-hs2[j+1]*b[i];
//            se.insert(h);
//            se.insert(f);
//            if(se.size()!=s) s++;
//            if(i==1) cout<<b[i]<<' ';
            if((!mp.count(h))&&(!mp.count(f))){
                s++;
                mp[h]=mp[f]=1;
            }
         }
         if(s>ans){
             ans=s;
             st[top=1]=i;
         }
         else if(s==ans) st[++top]=i;
//         if(i==2) cout<<s<<' 
    }
    printf("%d %d\n",ans,top);
    for(register int i=1;i<=top;i++) printf("%d ",st[i]);
    return 0;
}
View Code

 水题3

CDQ分治。。。

KD-Tree 应该也

那个啥有一个小点忘记讲了QAQ

x和y的值都很大,如果用BIT维护x或y轴显然是不太优的

所以要把x或y离散化

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <map>
#define ll long long
using namespace std;
const int N=2500000+10;
ll n,m,ans[N],cnt,tot,bt[N*2];
map<ll,ll>mp;
struct nod{
    ll x,y,id,val,opt;
    bool operator < (const nod&a) const {
        return x<a.x;
    }
}a[N];
struct tre{
    ll x,y;
    bool operator < (const tre&a) const {
        return y<a.y;
    }
}t[N];

void read(ll &x){
    x=0;ll f=1;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')f=-f;c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    x*=f;
}

ll lowbit(ll x){
    return x&(-x);
}

void update(ll x,ll v){
    for(ll i=x;i<=cnt;i+=lowbit(i)) bt[i]+=v;
}

ll query(ll x){
    ll ans=0;
    for(ll i=x;i;i-=lowbit(i)) ans+=bt[i];
    return ans;
}

nod q[N];
void cdq(ll l,ll r){
    if(l==r) return ;
    ll mid=(l+r)/2;
    cdq(l,mid);
    cdq(mid+1,r);
    int qwq=l-1,l1=l,l2=(l+mid)/2+1,m1=(l+mid)/2;
    while(l1<=m1&&l2<=mid){
        if(a[l2]<a[l1]) q[++qwq]=a[l2++];
        else q[++qwq]=a[l1++]; 
    }
    while(l1<=m1) q[++qwq]=a[l1++];
    while(l2<=mid) q[++qwq]=a[l2++];
    l1=mid+1;m1=(mid+1+r)/2;l2=m1+1;
    while(l1<=m1&&l2<=r){
        if(a[l2]<a[l1]) q[++qwq]=a[l2++];
        else q[++qwq]=a[l1++]; 
    }
    while(l1<=m1) q[++qwq]=a[l1++];
    while(l2<=r) q[++qwq]=a[l2++];
    for(int i=l;i<=r;i++) a[i]=q[i];
    ll j=l;
    for(ll i=mid+1;i<=r;i++){
        for(;j<=mid&&a[j].x<=a[i].x;j++)
            if(!a[j].opt) update(a[j].y,a[j].val);
//        cout<<1;
        if(a[i].opt) ans[a[i].id]+=a[i].val*query(a[i].y);
    }
    for(ll i=l;i<j;i++)
        if(!a[i].opt) update(a[i].y,-a[i].val);
}

ll b[N],aa[N],bc;
int main(){
//    freopen("QAQQWQ.in","r",stdin);
    read(n);read(m);
    for(ll i=1;i<=n;i++) read(t[i].x),read(t[i].y);
    sort(t+1,t+1+n);
    aa[0]=-1;
    for(ll i=1;i<=n;i++) aa[++bc]=t[i].y+1;
    for(ll i=1;i<=n;i++) a[++tot]=(nod){t[i].x+1,t[i].y+1,0,1,0};
    for(ll i=1;i<=m;i++){
        ll x1,x2,y1,y2;
        read(x2);read(y2);
        read(x1);read(y1);
        ++x2;++x1;++y1;++y2;
        a[++tot]=(nod){x1,y1,i,1,1};
        a[++tot]=(nod){x2-1,y2-1,i,1,1};
        a[++tot]=(nod){x1,y2-1,i,-1,1};
        a[++tot]=(nod){x2-1,y1,i,-1,1};
        aa[++bc]=y1;aa[++bc]=y2-1;
    }
    sort(aa+1,aa+1+bc);
    for(ll i=1;i<=bc;i++)
        if(aa[i]!=aa[i-1]) b[++cnt]=aa[i],mp[aa[i]]=cnt;
    for(ll i=1;i<=tot;i++) a[i].y=mp[a[i].y];
    cdq(1,tot);
    for(ll i=1;i<=m;i++) printf("%lld\n",ans[i]);
    return 0;
}
View Code

 

水题4

QAQ不会写...

容易发现有三种跳法 向两边往外跳 向内跳

会发现 这世上可以看成一棵树 

于是答案变成了两个节点间的距离

很遗憾如果我们直接求lca是不可行的

不过我们可以考虑让一个节点爬到和另一节点同一深度处

这直接除出跳的深度

这样的话效率就大大提高了,gcd?

这样来看我们可以二分节点爬的深度来解决这个问题

应该是这样?

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
int a[5],b[5],v,ans;
struct QAQ{
    int a[5];
    bool operator != (const QAQ&x) const {
        return !(x.a[3]==a[3]&&x.a[1]==a[1]&&x.a[2]==a[2]);
    }
};

void read(int &x){
    x=0;int f=1;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')f=-f;c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    x*=f;
}

QAQ calc(int a[],int k){
    QAQ ans;
    int t1=a[2]-a[1],t2=a[3]-a[2];
    for(int i=1;i<=3;i++) ans.a[i]=a[i];
    if(t1==t2) return ans;
    if(t1>t2){
        int t=min(k,(t1-1)/t2);
        k-=t;v+=t;
        ans.a[2]-=t*t2;
        ans.a[3]-=t*t2;
    }
    else {
        int t=min(k,(t2-1)/t1);
        k-=t;v+=t;
        ans.a[2]+=t*t1;
        ans.a[1]+=t*t1;
    }
    if(k) return calc(ans.a,k);
    else return ans;
}

int main(){
    for(int i=1;i<=3;i++) read(a[i]);
    for(int i=1;i<=3;i++) read(b[i]);
    sort(a+1,a+4);sort(b+1,b+4);
    QAQ t1=calc(a,1000000000);int b1=v;v=0;
    QAQ t2=calc(b,1000000000);int b2=v;v=0;
    if(t1!=t2){
        printf("NO");
        return 0;
    }
    else printf("YES\n");
    if(b1>b2){
        swap(b1,b2);
        swap(a,b);
    }
    ans=(b2-b1);
    t1=calc(b,ans);
    for(int i=1;i<=3;i++) b[i]=t1.a[i];
    int l=0,r=b2;
    while(l<r){
        int mid=(l+r)/2;
        if(calc(a,mid)!=calc(b,mid)) l=mid+1;
        else r=mid;
    }
    printf("%d",ans+2*r);
    return 0;
}
View Code

 

水题5

直接链表trie

#include <iostream>
#include <cstdio>
#define ll long long
using namespace std;
const int N=5000000+10;
int n,val[N],v[N],nxt[N],first[N],cnt,sz=1;
ll ans;
char w[N],c;

void add(int a,int b,char c){
    v[++cnt]=b;
    nxt[cnt]=first[a];
    w[cnt]=c;
    first[a]=cnt;
}

void insert(){
    c=getchar();
    int u=0,t=1;
    while(c=='\n') c=getchar();
    for(int i=1;c!='\n';i++,c=getchar()){
        u=0;
        for(int j=first[t];j;j=nxt[j])
            if(w[j]==c){
                u=v[j];
                break;
            }
        if(!u) add(t,u=++sz,c);
        t=u;
        val[u]++;
        ans=max(ans,1ll*val[u]*1ll*i);
    }
}

int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++) insert();
    printf("%lld",ans);
    return 0;
}
View Code

 

水题6

世上这就是个基环树森林

所以直接断边做树形dp

dp[x][0/1]表示不选或选x的最大值

dp[x][0]+=max{dp[son[x]][1],dp[son[x]][0]}

dp[x][1]+=max{dp[son[x]][0]} 

#include <iostream>
#include <cstdio>
#define ll long long
using namespace std;
const int N=1000000+10;
int v[N*2],nxt[N*2],first[N],cnt=1;
int n,m,val[N];
ll ans,dp[N][2];
bool vis[N],fl[N*2],QAQ;

void read(int &x){
    x=0;int f=1;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')f=-f;c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    x*=f;
}

void add(int a,int b){
    v[++cnt]=b;
    nxt[cnt]=first[a];
    first[a]=cnt;
}

int s,t;
void dfs(int x,int y){
    vis[x]=1;
    for(int i=first[x];i&&QAQ;i=nxt[i]){
        if(v[i]==y) continue;
        if(vis[v[i]]){
            fl[i]=fl[i^1]=1;
            s=x;t=v[i];
            QAQ=0;
            break;
        }
        else dfs(v[i],x);
    }
}

void getdp(int x,int y,int qwq){
    vis[x]=1;
    if(x==qwq) dp[x][1]=0ll;
    else dp[x][1]=(ll)val[x];
    dp[x][0]=0ll;
    for(int i=first[x];i;i=nxt[i]){
        if(y==v[i]||fl[i]) continue;
        getdp(v[i],x,qwq);
        dp[x][1]+=dp[v[i]][0];
        dp[x][0]+=max(dp[v[i]][1],dp[v[i]][0]);
    }
}

int main(){
    read(n);
    for(int i=1;i<=n;i++){
        read(val[i]);
        int x;
        read(x);
        add(x,i);
        add(i,x);
    }
    for(int i=1;i<=n;i++){
        if(vis[i]) continue;
        QAQ=1;
        ll mx=0;
        dfs(i,0);
        getdp(s,0,t);
        mx=max(dp[s][0],dp[s][1]);
        getdp(t,0,s);
        ans+=max(mx,max(dp[t][0],dp[t][1]));
    }
    printf("%lld",ans);
    return 0;
}
View Code

 

水题7

太久没填坑了,就随便放几道水题吧qwq

随便推一下会发现 原式=∑nD=1 F(n/D,m/D)*G(D)

 其中 F(n,m)=(1+n)*n-n*(2n+1)(n+1)/3+n*(n+m+1)(m-n)/2-(m-n)(1+n)*n/2

    G(D)=∑k|D miu(k)*k

#include <iostream>
#include <cstdio>
using namespace std;
#define ll long long
const int N=2000000+10;
const int mod1=1000000000+7;
const int mod2=mod1+2;
int g1[N],g2[N],pri[N],cnt;
int inv2,inv3,inv4,inv6;
bool isp[N];
  
void read(int &x){
    x=0;int f=1;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')f=-f;c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    x*=f;
}
  
void euler(){
    g1[1]=g2[1]=1;
    isp[1]=1;
    for(int i=2;i<N;i++){
        if(!isp[i]){
            pri[++cnt]=i;
            g1[i]=((1-i)%mod1+mod1)%mod1;
            g2[i]=((1-i)%mod2+mod2)%mod2;
        }
        for(int j=1;j<=cnt&&i*pri[j]<N;j++){
            isp[i*pri[j]]=1;
            if(i%pri[j]==0){
                g1[i*pri[j]]=g1[i];
                g2[i*pri[j]]=g2[i];
                break;
            }
            g1[i*pri[j]]=1ll*g1[i]*g1[pri[j]]%mod1;
            g2[i*pri[j]]=1ll*g2[i]*g2[pri[j]]%mod2;
        }
    }
    for(int i=1;i<N;i++) g1[i]=(g1[i-1]+1ll*g1[i])%mod1;
    for(int i=1;i<N;i++) g2[i]=(g2[i-1]+1ll*g2[i])%mod2;
}
  
int f1(int n,int m){
    return ((((((1ll*(1ll*(1+n)%mod1*n%mod1*n%mod1)-1ll*(1ll*(2*n+1)%mod1*n%mod1*(n+1)%mod1)*inv3%mod1)%mod1)+1ll*n*(n+m+1)%mod1*(m-n)%mod1*inv2%mod1)%mod1)-1ll*(m-n)*(1+n)%mod1*n%mod1*inv2%mod1)%mod1+mod1)%mod1;
}
  
int f2(int n,int m){
    return ((((((1ll*(1ll*(1+n)%mod2*n%mod2*n%mod2)-1ll*(1ll*(2*n+1)%mod2*n%mod2*(n+1)%mod2)*inv6%mod2)%mod2)+1ll*n*(n+m+1)%mod2*(m-n)%mod2*inv4%mod2)%mod2)-1ll*(m-n)*(1+n)%mod2*n%mod2*inv4%mod2)%mod2+mod2)%mod2;
}
  
int main(){
    inv2=500000004;
    inv3=333333336;
    inv4=500000005;
    inv6=666666673;
    euler();
    int t;
    read(t);
    while(t--){
        int n,m;
        read(n);read(m);
        if(n>m) swap(n,m);
        ll ans1=0,ans2=0;
        for(int l=1,r;l<=n;l=r+1){
            r=min(n/(n/l),m/(m/l));
            ans1=(ans1+1ll*f1(n/l,m/l)*(((1ll*g1[r]-g1[l-1])%mod1+mod1)%mod1)%mod1)%mod1;
            ans2=(ans2+1ll*f2(n/l,m/l)*(((1ll*g2[r]-g2[l-1])%mod2+mod2)%mod2)%mod2)%mod2;
        }
        printf("%lld %lld\n",ans1,ans2);
    }
    return 0;
}
View Code

 

【7/12】((๑°ㅁ°๑)ᵎᵎᵎ  怎么又多了

 

posted @ 2018-08-18 15:09  lyf2  阅读(253)  评论(9编辑  收藏  举报