UESTC 2016 Summer Training #5 Div.2(未完待续)

A

#include <cstdio>
#include <cstring>
#include <vector>
#define MAXN 100005
#define mem(a) memset(a, 0, sizeof(a))
using namespace std;

int TreeArray[MAXN], Left[MAXN], Right[MAXN], Fork[MAXN];
typedef vector<int> Ve;
vector<Ve>Edge(MAXN);
int N,M;
int key;

void init()//初始化数组和
{
    mem(Left);  mem(Right);
    mem(Fork);  mem(TreeArray);
    for(int i=0;i<MAXN;i++)Edge[i].clear();
}

void DFS(int node)//为每一个node添加一个左值和右值,表示这个节点所
{
    Left[node] = key;
    for(int i=0;i<Edge[node].size();i++)
    {
        key+=1;
        DFS(Edge[node][i]);
    }
    Right[node] = key;
}

int LowBit(int x)//返回的是2^k
{
    return x & (x ^ (x-1));
}

void Edit(int k, int num)//修改节点k,如果是添加一个,代入1,删除一个代入-1
{
    while(k <= N)
    {
        TreeArray[k] += num;
        k += LowBit(k);
    }
}

int GetSum(int k)//得到1...k的和
{
    int sum = 0;
    while(k>=1)
    {
        sum += TreeArray[k];
        k -= LowBit(k);
    }
    return sum;
}

void ReadDataAndDo()
{
    int a,b;
    char ch;
    for(int i=1;i<N;i++)//输入a,b把边存放在容器里面
    {
        scanf("%d%d", &a, &b);
        Edge[a].push_back(b);
    }
    key = 1;    DFS(1);//为每一个节点对应一个左边界和右边界,他自己就存放在左边界里面,而它的管辖范围就是左边界到右边界
    for(int i=1;i<=N;i++)
    {
        Fork[i] = 1;//最初每个Fork上都有一个苹果
        Edit(i,1);//同时更新树状数组的值
    }
    scanf("%d%*c", &M);
    for(int i=0;i<M;i++)
    {
        scanf("%c %d%*c", &ch, &b);
        if(ch == 'Q')//b的子树就是[Left[b], right[b]]
        {
            printf("%d\n", GetSum(Right[b]) - GetSum(Left[b]-1));
        }
        else
        {
            if(Fork[b]) Edit(Left[b],-1);//由于每个节点的编号就是它的左值,所以直接修改左节点
            else Edit(Left[b],1);
            Fork[b] = !Fork[b];//变为相反的状态
        }
    }
}

int main()
{
    while(~scanf("%d", &N))
    {
        init();
        ReadDataAndDo();
    }
    return 0;
}

B

#include <bits/stdc++.h>  
using namespace std;  
int n,q,x;  
int main(){  
    int a=0,b=0;  
    scanf("%d%d",&n,&q);  
    while(q--){  
        int tmp;  
        scanf("%d",&tmp);  
        if(tmp==1){  
            scanf("%d",&x);  
            a = (n+a-x)%n;  
            b = (n+b-x)%n;  
            if(x%2) swap(a,b); //x为奇数时,1,2的位置奇偶性必然改变成相反的  
        }else{  
            a = (a+n-1)%n;  
            b = (b+n+1)%n;  
            swap(a,b);//交换奇偶位置  
        }  
    }  
    for(int i=1; i<=n; i++){  
        if(i%2) printf("%d ",(a+i-1+n)%n+1);//1的位置递推所有奇数位置的编号  
        else printf("%d ",(b+i-1+n)%n+1); //2的位置递推所有偶数位置的编号  
    }  
    return 0;  
}  

C

#include <stdio.h>
#include <algorithm>
#include <iostream>
#include <string.h>
#include <math.h>

#define INF 0x3f3f3f3f
#define eps 1e-6

typedef long long LL;
const double pi = acos(-1.0);
const long long Mod = INF;
using namespace std;

int main()
{
    LL M,N;
    cin >> N >> M;
    LL k = 2;
    LL a = N / M;
    printf("%I64d",a);
    N = (N - a * M) * k;
    while(N)
    {
        a = N / M;
        printf(" %I64d",a);
        k++;
        N = (N - a * M) * k;
    }
    puts("");
    return 0;
}

D

#include <stdio.h>
#include <algorithm>
#include <iostream>
#include <string.h>
#include <math.h>

#define INF 0x3f3f3f3f
#define eps 1e-6

typedef long long LL;
const double pi = acos(-1.0);
const long long MOD = 1e9 + 7;
using namespace std;

struct node
{
    int u,v,w;
}edge[10005];

int dis[10005];

int top;

int fun(int N)
{
    int u,v,w;
    for(int i = 1;i <= N;i++)
        dis[i] = INF;
    dis[1] = 0;
    for(int k = 0;k < N - 1;k++)
        for(int i = 0;i < top;i++)
        {
            u = edge[i].u;
            v = edge[i].v;
            w = edge[i].w;
            if(dis[u] + w < dis[v] && dis[u] < INF)
                dis[v] = dis[u] + w;
        }
    for(int i = 0;i < top;i++)
    {
        u = edge[i].u;
        v = edge[i].v;
        w = edge[i].w;
        if(dis[u] + w < dis[v] && dis[u] < INF)
            return 0;
    }
    return 1;
}

void add(int u,int v,int w)
{
    edge[top].u = u;
    edge[top].v = v;
    edge[top++].w = w;
}

int main()
{
    int F,N,M,W,T,S,E;
    cin >> F;
    while(F--)
    {
        top = 0;
        cin >> N >> M >> W;
        for(int i = 0;i < M;i++)
        {
            cin >> S >> E >> T;
            add(S,E,T);
            add(E,S,T);
        }
        for(int i = 0;i < W;i++)
        {
            cin >> S >> E >> T;
            add(S,E,-T);
        }
        if(!fun(N))
            puts("YES");
        else
            puts("NO");
    }
    return 0;
}

E
题目大意:

妈妈烧了M根骨头分给n个孩子们,第i个孩子有两个参数Mini和Maxi,分别表示这个孩子至少要得到Mini根骨头,至多得到Maxi根骨头。
输出一个整数,表示妈妈有多少种分配方案(骨头不能浪费,必须都分给孩子们)。

思路:

所以我们可以通过换元法,让下界的限制变成得到简单形式。
但是很遗憾的是,对于上界的限制,我们无法直接计算出答案。
逆向思维
于是根据容斥原理来做有:

import java.io.*;  
import java.math.BigInteger;  
import java.util.*;  

public class Main {  
    public static void main(String args[]) throws Exception {  
        InputStream inputStream = System.in;  
        OutputStream outputStream = System.out;  
        InputReader in = new InputReader(inputStream);  
        PrintWriter out = new PrintWriter(outputStream);  
        Task solver = new Task();  
        solver.main(in, out);  
        out.close();  
    }  
}  

class InputReader {  
    BufferedReader reader;  
    StringTokenizer tokenizer;  

    public InputReader(InputStream stream) {  
        reader = new BufferedReader(new InputStreamReader(stream));  
        tokenizer = null;  
    }  

    public String next() {  
        if (!hasNext())  
            throw new RuntimeException();  
        return tokenizer.nextToken();  
    }  

    boolean hasNext() {  
        while (tokenizer == null || !tokenizer.hasMoreTokens())  
            try {  
                tokenizer = new StringTokenizer(reader.readLine());  
            } catch (Exception e) {  
                return false;  
            }  
        return true;  
    }  

    public long nextLong() {  
        return Long.parseLong(next());  
    }  

    public int nextInt() {  
        return Integer.parseInt(next());  
    }  
}  

class Task {  
    BigInteger zero = BigInteger.ZERO;  
    BigInteger one = BigInteger.ONE;  
    BigInteger ten = BigInteger.TEN;  
    final int maxn = 50005;  
    BigInteger[] f=new BigInteger[maxn];  
    int[] A=new int [15];  
    int[] B=new int [15];  
    int n,m;  
    BigInteger ans;  
    BigInteger C(int n,int m)  
    {  
        if(m>n)  
            return zero;  
        m=Math.min(m, n-m);  
        BigInteger res=one;  
        for(int i=n;i>=n-m+1;--i)  
        {  
            res=res.multiply(BigInteger.valueOf(i)).divide(BigInteger.valueOf(n-i+1));  
        }  
        return res;  
    }  
    void gao(int x,int cnt,int remain)  
    {  
        if(x<0)  
        {  
            if((cnt&1)>0)  
                ans=ans.subtract(C(remain+n-1,n-1));  
            else  
                ans=ans.add(C(remain+n-1,n-1));  
            return;  
        }  
        gao(x-1,cnt,remain);  
        if(remain>B[x])  
            gao(x-1,cnt+1,remain-B[x]-1);  
    }  
    void main(InputReader in, PrintWriter out) throws Exception {  
        int i,j;  
        ans=zero;  
        int T;  
        T=in.nextInt();  
        for(int cas=0;cas<T;++cas)  
        {  
            ans=zero;  
            n=in.nextInt();  
            m=in.nextInt();  
            for(i=0;i<n;++i)  
            {  
                A[i]=in.nextInt();  
                B[i]=in.nextInt();  
                m-=A[i];  
                B[i]-=A[i];  
            }  
            if(m<0)  
            {  
                out.println(0);  
            }  
            else if(m==0)  
            {  
                out.println(1);  
            }  
            else  
            {     
                gao(n-1,0,m);  
                out.println(ans);  
            }  
        }  
    }  
}  

F
题意:给你一个数N,让你用前N个数,通过N-1次加减乘除运算得到24。让你输出合法的计算过程。
做法:
当N<4时,很显然,无法得到24点;
当N>=4时,可以得到24点,这时,我们分成两种情况进行构造。
1)当N为偶数时,由1,2,3,4显然可以构造出24,剩下的N-4(偶数)个数只需两两相减,并最后与24相乘即可。
2)当N为奇数时,由1,2,3,4,5显然可以构造出24,剩下的N-5(偶数)个数只需两两相减,并最后与24相乘即可。具体实现方法见代码。

#include <stdio.h>
#include <algorithm>
#include <iostream>
#include <string.h>
#include <math.h>

#define INF 0x3f3f3f3f
#define eps 1e-6

typedef long long LL;
const double pi = acos(-1.0);
const long long MOD = 1e9 + 7;
using namespace std;

int a[12] = {0};

int main()
{
    int N;
    cin >> N;
    int ok = 1;
    if(N < 4)
    {
        puts("NO");
        return 0;
    }
    else
        puts("YES");
    if(N % 2 == 0)
    {
        printf("2 * 3 = 6\n");
        printf("4 * 6 = 24\n");
        printf("24 * 1 = 24\n");
        for(int i = 5;i < N;i += 2)
        {
            printf("%d - %d = 1\n",i + 1,i);
            printf("24 * 1 = 24\n");
        }
    }
    else
    {
        printf("4 * 5 = 20\n");
        printf("20 + 3 = 23\n");
        printf("23 + 2 = 25\n");
        printf("25 - 1 = 24\n");
        for(int i = 6;i < N;i += 2)
        {
            printf("%d - %d = 1\n",i + 1,i);
            printf("24 * 1 = 24\n");
        }
    }
    return 0;
}

G

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define mod 1000000007
#define esp 0.00000000001
const int N=2e5+10,M=1e6+10,inf=1e9;
#define mem(s) memset(s,0,sizeof(s))
int n,m,head[N],t,vis[N],deep[N],fa[N][20];
int a[N];
int flag[N];
struct ss {
  int to,next;
}e[N*2];
void add(int u,int v) {
   e[t].next=head[u];e[t].to=v;head[u]=t++;
}
void init() {
  t=1;mem(head);mem(vis);mem(fa);mem(deep);mem(flag);
}
void dfs(int x) {
    vis[x]=1;
    for (int i=1; i<=18 ;i++) {
        if(deep[x]<(1<<i)) break;
        fa[x][i] = fa[fa[x][i-1]][i-1];
    }
    for (int i=head[x];i;i=e[i].next) {
        if(vis[e[i].to]) continue;
        deep[e[i].to]=deep[x]+1;
        fa[e[i].to][0]=x;
        dfs(e[i].to);
    }
}
int RMQ_LCA(int x,int y) {
    if(deep[x]<deep[y]) swap(x,y);
    int d=deep[x]-deep[y];
    for (int i=0; i<=18 ;i++)
        if((1<<i)&d) x=fa[x][i];
    for (int i=18; i>=0 ;i--) {
        if(fa[x][i]!=fa[y][i]) {
            x=fa[x][i];y=fa[y][i];
        }
    }
    if(x==y) return x;
    else return fa[x][0];
}
int Dis_LCA(int x,int y) {
    int LCA= RMQ_LCA(x,y);
    return (deep[x]+deep[y]-2*deep[LCA]);
}
struct is
{
    int pos,step,pre;
};
int main()
{
    int x,y,z,i,t;
    while(~scanf("%d",&x))
    {
        queue<is>q;
        init();
        for(i=2;i<=x;i++)
        scanf("%d",&a[i]);
        for(i=x;i>=2;i--)
        {
            add(a[i],i);
            add(i,a[i]);
        }
        dfs(1);
        int maxdeep=0;
        int pre=0;
        is st;
        st.pos=1;
        st.step=0;
        st.pre=0;
        q.push(st);
        flag[1]=1;
        ll ans=0;
        while(!q.empty())
        {
            is vv=q.front();
            q.pop();
            if(vv.pos!=1)
            {
                ans+=Dis_LCA(vv.pos,pre);
            }
            pre=vv.pos;
            maxdeep=vv.step;
            int pos=vv.pos;
            for(i=head[vv.pos];i;i=e[i].next)
            {
                if(flag[e[i].to])
                continue;
                is en;
                en.pos=e[i].to;
                en.step=vv.step+1;
                en.pre=vv.pos;
                flag[e[i].to]=1;
                q.push(en);
            }
        }
        printf("%lld\n",ans);
    }
    return 0;
}

I

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <algorithm>
#include <set>
using namespace std;
typedef long long ll;
typedef unsigned long long Ull;
#define MM(a,b) memset(a,b,sizeof(a));
const double eps = 1e-10;
const int  inf =0x7f7f7f7f;
const double pi=acos(-1);
const int maxn=40000;

struct node {
   int x,y;
   bool operator<(const node&a) const{
       return this->x<a.x;
   }
};
vector<node> A,B;
char s[10000];
int main()
{
    int n;
    while(~scanf("%d",&n))
    {
        A.clear();B.clear();
        for(int i=1;i<=n;i++)
        {
            scanf("%s",s);
            int l=0,r=0;
            for(int j=0;s[j]!='\0';j++)
            {
                 if(s[j]=='(') r++;
                 else if(!r) l++;
                 else r--;
            }
            if(l>r) B.push_back((node){r,l-r});
            else  A.push_back((node){l,r-l});
        }

        sort(A.begin(),A.end());
        sort(B.begin(),B.end());
        int cntA=0,cntB=0;

        bool flag=true;
        for(int i=0;i<A.size();i++)
        {
            if(A[i].x>cntA) {flag=false;break;}
            cntA+=A[i].y;
        }

        for(int i=0;i<B.size();i++)
        {
            if(B[i].x>cntB) {flag=false;break;}
            cntB+=B[i].y;
        }

        if(cntA!=cntB) flag=false;
        printf("%s\n",flag?"Yes":"No");
    }
    return 0;
}

K

题意:让你读完文章,并依次得到每个人的比赛次数。一共11个人,并且已经个了3个,你可以用这三个数检验你自己的答案。
傻逼题,细心阅读就可以了

#include <stdio.h>
#include <algorithm>
#include <iostream>
#include <string.h>
#include <math.h>

#define INF 0x3f3f3f3f
#define eps 1e-6

typedef long long LL;
const double pi = acos(-1.0);
const long long Mod = INF;
using namespace std;

int a[12] = {5,20,12,2,1,4,6,1,4,4,1,0};

int main()
{
    int n;
    cin >> n;
    printf("%d\n",a[n]);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值