2017ACM/ICPC广西邀请赛-重现赛

比赛过题:ADEFGJ
补题:BCH

A

签到

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;

LL qpow(LL x,LL n)
{
    LL ret=1;
    for(;n;n>>=1)
    {
        if(n&1) ret=ret*x;
        x=x*x;
    }
    return ret;
}

LL a[25];
void init()
{
    for(int i=1;i<=20;i++)
        a[i]=qpow(i,i);
}

int main()
{
    init();
    LL n;
    while(cin>>n)
    {
        LL ans=upper_bound(a,a+16,n)-a-1;
        cout<<ans<<endl;
    }
}

B

动态开点线段树+剪枝

#include<bits/stdc++.h>
using namespace std;
const int H=1e6,N=150000*30,INF=1e9+7;
int root[57],mn[N],ls[N],rs[N],tot,X;
bool ok;
int newnode()
{
    mn[++tot]=INF;
    ls[tot]=rs[tot]=0;
    return tot;
}
void update(int &rt,int l,int r,int p,int val)
{
    if(!rt) rt=newnode();
    mn[rt]=min(mn[rt],val);
    if(l==r) return ;
    int m=(l+r)>>1;
    if(p<=m) update(ls[rt],l,m,p,val);
    else update(rs[rt],m+1,r,p,val);
}
void query(int rt,int l,int r,int ql,int qr)
{
    if(ok) return;
    if((ql<=l&&qr>=r)||(ls[rt]==0&&rs[rt]==0))
    {
        if(mn[rt]<=X) ok=true;
        return ;
    }
    int m=(l+r)>>1;
    if(ql<=m&&ls[rt]) query(ls[rt],l,m,ql,qr);
    if(qr>m&&rs[rt]) query(rs[rt],m+1,r,ql,qr);
}
int main()
{
    int op;
    tot=0;
    for(int i=0;i<=50;++i) root[i]=newnode();
    while(~scanf("%d",&op))
    {
        if(op==3) break;
        if(op==0)
        {
            tot=0;
            for(int i=0;i<=50;++i) root[i]=newnode();
        }
        if(op==1)
        {
            int x,y,c;
            scanf("%d%d%d",&x,&y,&c);
            update(root[c],1,H,y,x);
        }
        else if(op==2)
        {
            int x,y1,y2,ans=0;
            scanf("%d%d%d",&x,&y1,&y2);
            X=x;
            for(int i=0;i<=50;++i)
            {
                ok=false;
                query(root[i],1,H,y1,y2);
                ans+=ok;
            }
            printf("%d\n",ans);
        }
    }
    return 0;
}

C

三元环

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;

namespace IO {  
    const int MX = 2e7; //1e7占用内存11000kb  
    char buf[MX]; int c, sz;  
    void begin() {  
        c = 0;  
        sz = fread(buf, 1, MX, stdin);  
    }  
    inline bool read(int &t) {  
        while(c < sz && buf[c] != '-' && (buf[c] < '0' || buf[c] > '9')) c++;  
        if(c >= sz) return false;  
        bool flag = 0; if(buf[c] == '-') flag = 1, c++;  
        for(t = 0; c < sz && '0' <= buf[c] && buf[c] <= '9'; c++) t = t * 10 + buf[c] - '0';  
        if(flag) t = -t;  
        return true;  
    }  
}

const int N=1e5+3;
int n,m;
vector<int> adj[N];
LL ans;
map<pair<int,int>,int> mp; 

int d[N];
int link[N];
int l[2*N],r[2*N];

void init()
{
    ans=0;
    mp.clear();
    for(int i=1;i<=n;i++)
        adj[i].clear(),d[i]=0,link[i]=0;
}

pair<int,int> Union(int u,int v)
{
    return make_pair(min(u,v),max(u,v));
}

void add(int u1,int u2,int u3)
{
    mp[Union(u1,u2)]++;
    mp[Union(u3,u2)]++;
    mp[Union(u1,u3)]++;
}

void solve()
{
    for(int i=0;i<m;i++)
    {
        int u=l[i],v=r[i];
        for(int x:adj[u])
            link[x]=u;
        for(int x:adj[v])
            if(link[x]==u) add(u,v,x);
    }
    for(map<pair<int,int>,int>::iterator it=mp.begin();it!=mp.end();++it)
    {
        int t=it->second;
        ans+=t*(t-1)/2;
    }
}

int main()
{
//  freopen("test.in","r",stdin);
    IO::begin();
//  while(~scanf("%d%d",&n,&m))
    while(IO::read(n))
    {
        IO::read(m);
        init();
        for(int i=0;i<m;i++)
        {
            IO::read(l[i]),d[l[i]]++;
            IO::read(r[i]),d[r[i]]++;
        }
        for(int i=0;i<m;i++)
        {
            if(d[l[i]]>d[r[i]]||d[l[i]]==d[r[i]]&&l[i]>r[i])
                swap(l[i],r[i]);
            adj[l[i]].push_back(r[i]);
        }
        solve();
        printf("%lld\n",ans);
    }
}

D

4*n骨牌覆盖

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;

const int N=16;
const int mod=1000000007;

LL b[N]={1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
LL hh[N][N]=
{
    {1,0,0,1,0,0,0,0,0,1,0,0,1,0,0,1},
    {0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0},
    {0,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0},
    {1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0},
    {0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0},
    {0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0},
    {0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0},
    {0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0},
    {0,1,0,0,1,0,0,1,0,0,0,0,0,0,0,0},
    {1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0},
    {0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0},
    {0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0},
    {1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0},
    {0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0},
    {0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
    {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
};

struct Mat
{
    LL mat[16][16];
    LL* operator[] (int x)
    {
        return mat[x];
    }
}A[65];

Mat Mut(Mat a,Mat b)
{
    Mat c;
    memset(c.mat,0,sizeof(c.mat));
    for(int i=0;i<N;i++)
        for(int k=0;k<N;k++) if(a[i][k])
            for(int j=0;j<N;j++)
            {
                c[i][j]+=a[i][k]*b[k][j];
                c[i][j]%=mod;
            }
    return c;
}

void init_A()
{
    for(int i=0;i<N;i++)
        for(int j=0;j<N;j++)
            A[0][i][j]=hh[i][j];
    for(int i=1;i<64;i++)
        A[i]=Mut(A[i-1],A[i-1]);
}


LL cal(LL n)
{
    LL b_[N];
    memcpy(b_,b,sizeof(b));
    for(int p=0;n;n>>=1)
    {
        if(n&1)
        {
            LL temp[N]={0};
            for(int i=0;i<N;i++)
                for(int j=0;j<N;j++)
                    temp[i]=(temp[i]+A[p][i][j]*b_[j])%mod;
            memcpy(b_,temp,sizeof(b_));
        }
        p++;
    }
    return b_[0];
}

int main()
{
    init_A();
    LL n;
//  n=(1LL<<60)-1;
//  int T=5000;
//  while(T--)
//      cal(n);
    while(~scanf("%lld",&n))
        printf("%lld\n",cal(n));
}

E

水题

#include <cstdio>
#include <cstring>
using namespace std;
typedef long long ll;
const int N=100005;
ll n,a[N],b0[30],b1[30],X,q;
ll AND(ll p){
    ll ans=0;
    for(ll i=0;i<30;++i){
        if(((a[p]>>i)%2==0&&b0[i]==1)||b0[i]==0){
            ans+=(1<<i);
        }
    }
    return ans;
}
ll OR(ll p){
    ll ans=0;
    for(ll i=0;i<30;++i){
        if(b1[i]==0)continue;
        if((a[p]>>i)%2==1&&b1[i]==1)continue;
        ans+=(1<<i);
    }
    return ans;
}
ll XOR(ll p){
    return X^a[p];
}
int main(void){
    while(~scanf("%I64d%I64d",&n,&q)){
        memset(b0,0,sizeof(b0));
        memset(b1,0,sizeof(b1));
        X=0;
        for(ll i=0;i<n;++i){
            scanf("%I64d",&a[i]);
            X^=a[i];
            for(ll j=0;j<30;++j){
                if((a[i]>>j)&1)b1[j]++;
                else b0[j]++;
            }
        }
        while(q--){
            ll p;
            scanf("%I64d",&p);p--;
            printf("%I64d %I64d %I64d\n",AND(p),OR(p),XOR(p));
        }
    }
}

F

最小生成树

#include <queue>
#include <cstdio>
#include <set>
using namespace std;
const int N=200005;
int n,m,pre[N];
set<int>s;
struct node{
    int w,u,v;
    node(int U,int V,int W){
        w=W;u=U;v=V;
    }
    friend bool operator<(node a,node b){
        return a.w>b.w;
    }
};
void init(int n){
    for(int i=0;i<=n;++i)
        pre[i]=i;
}
int Find(int x){
    return pre[x]==x?x:pre[x]=Find(pre[x]);
}
void Union(int x,int y){
    int a=Find(x),b=Find(y);
    if(a!=b)pre[a]=b;
}
priority_queue<node>q;
int main(void){
    while(~scanf("%d%d",&n,&m)){
        init(n);
        while(!q.empty())q.pop();
        s.clear();
        for(int i=0;i<n;++i){
            int x,y;
            scanf("%d%d",&x,&y);
        }
        for(int i=0;i<m;++i){
            int u,v,w;
            scanf("%d%d%d",&u,&v,&w);
            q.push(node(u,v,-w));
            Union(u,v);
        }
        int p=-1;
        for(int i=1;i<=n;++i){
            if(p==-1)p=Find(i);
            s.insert(Find(i));
        }
        for(set<int>::iterator it=s.begin();it!=s.end();++it){
            if(p!=*it)q.push(node(p,*it,0));
        }
        init(n);
        int ans1=0,ans2=0;
        while(!q.empty()){
            node t=q.top();q.pop();
            int u=t.u,v=t.v,w=t.w;
            if(Find(u)!=Find(v)){
                Union(u,v);
            }else{
                ans1++;
                ans2-=w;
            }
        }
        printf("%d %d\n",ans1,ans2);
    }
}

G

贪心+dp

#include <cstdio>
#include <cstring>
using namespace std;
typedef long long ll;
const int N=1000005;
int n,a[N],t,dp[N][3];
int Max(int a,int b){
    return a>b?a:b;
}
int solve(int p,int res){
    if(p>n)return 0;
    if(dp[p][res]!=-1)return dp[p][res];
    int ans=0;
    if(res==2)ans=Max(ans,solve(p+1,a[p+1])+1);
    if(res==1&&p+2<=n&&a[p+1]>=1&&a[p+2]>=1)ans=Max(ans,solve(p+2,a[p+2]-1)+1);
    ans=Max(ans,solve(p+1,a[p+1]));
    return dp[p][res]=ans;
}
int main(void){
    while(~scanf("%d",&n)){
        memset(a,0,sizeof(a));
        memset(dp,-1,sizeof(dp));
        for(int i=0;i<n;++i){
            scanf("%d",&t);
            a[t]++;
        }
        int ans=0;
        for(int i=1;i<=n;++i){
            if(a[i]>2){
                t=a[i]-1;
                ans+=t/2;
                a[i]=1+t%2;
            }
        }
        ans+=solve(1,a[1]);
        printf("%d\n",ans);
    }
}

H

数论

#include <cstdio>
using namespace std;
typedef long long ll;
ll n,a,m;
ll powmod(ll a,ll n){
    ll r=1;
    while(n){
        if(n&1)r=r*a%m;
        a=a*a%m;;
        n>>=1;
    }
    return r;
}
int main(void){
    while(~scanf("%I64d%I64d",&n,&a)){
        if(n==0)printf("1\n");
        else if(a&1)printf("1\n");
        else{
            m=1<<n;
            ll ans=0;
            for(ll b=1;b<n;++b)
                if(powmod(a,b)==powmod(b,a))
                    ans++;
            for(ll i=1;i<=n;++i)
            if(a*i>=n){
                ans+=m/(1<<i)-(n-1)/(1<<i);
                break;
            }
            printf("%I64d\n",ans);
        }
    }
}

J

可持久化Trie

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+7;
int a[N],root[N],s[N*35][2],c[N*35],tot,sz[N],id[N],ord;
vector<int> adj[N];
void update(int &rt,int last,int x,int d)
{
    rt=++tot;
    s[rt][0]=s[last][0];
    s[rt][1]=s[last][1];
    c[rt]=c[last]+1;
    if(d==-1) return ;
    int b=(x>>d)&1;
    if(b^1) update(s[rt][0],s[last][0],x,d-1);
    else update(s[rt][1],s[last][1],x,d-1);
}
void dfs(int u,int p)
{
    id[u]=++ord;
    sz[u]=1;
    update(root[ord],root[ord-1],a[u],29);
    for(int v : adj[u])
    {
        if(v==p) continue;
        dfs(v,u);
        sz[u]+=sz[v];
    }
}
int query(int rt1,int rt2,int x,int d,int res)
{
    if(d==-1) return res;
    int b=((x>>d)&1)^1;
    int val=c[s[rt2][b]]-c[s[rt1][b]];
    if(val) return query(s[rt1][b],s[rt2][b],x,d-1,res|(1<<d));
    else return query(s[rt1][b^1],s[rt2][b^1],x,d-1,res);
}
int main()
{
    int n,q;
    while(~scanf("%d%d",&n,&q))
    {
        for(int i=1;i<=n;++i) adj[i].clear();
        memset(s,0,sizeof(s));
        memset(c,0,sizeof(c));
        ord=tot=0;
        for(int i=1;i<=n;++i) scanf("%d",&a[i]);
        for(int u=2;u<=n;++u)
        {
            int v;
            scanf("%d",&v);
            adj[v].push_back(u);
        }
        dfs(1,0);
        while(q--)
        {
            int x,y;
            scanf("%d%d",&y,&x);
            printf("%d\n",query(root[id[y]-1],root[id[y]+sz[y]-1],x,29,0));
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值