UESTC 2016 Summer Training #5 Div.2(未完待续)
2016-07-15 18:54
691 查看
A
B
C
D
E
题目大意:
妈妈烧了M根骨头分给n个孩子们,第i个孩子有两个参数Mini和Maxi,分别表示这个孩子至少要得到Mini根骨头,至多得到Maxi根骨头。
输出一个整数,表示妈妈有多少种分配方案(骨头不能浪费,必须都分给孩子们)。
思路:
所以我们可以通过换元法,让下界的限制变成得到简单形式。
但是很遗憾的是,对于上界的限制,我们无法直接计算出答案。
逆向思维
于是根据容斥原理来做有:
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相乘即可。具体实现方法见代码。
G
I
K
题意:让你读完文章,并依次得到每个人的比赛次数。一共11个人,并且已经个了3个,你可以用这三个数检验你自己的答案。
傻逼题,细心阅读就可以了
#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 ,t,vis ,deep ,fa [20]; int a ; int flag ; 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 ); return 0; }
相关文章推荐
- NGUI 背包滑动整合
- HoloLens开发手记 - Known issues 已知问题
- java 解析json 遍历未知key与value
- String 的个人理解以及在栈堆的内存以及Stringbuilder和Stringbuffer
- 约束报错、冲突如何定位UI
- 快速(quick)排序算法
- UITableView的优化技巧
- View跳转到Controller先创建控制器
- 完美解决jsp页面在IE8下文本模式自动为(杂项Quirks)导致页面显示错位的情况
- 图片的旋转动画
- vue-cli创建项目
- 自动计算UILabel的宽度或则高度
- 1. Two Sum QuestionEditorial Solution My Submissions
- mui几种页面跳转方式对比
- 判断UItextFiled只包含小数点后一位且是5
- UESTC 982质因子分解
- Android UI(EditText)详解
- 当前视图是在UIWindow上,所以需要拿到主window,判断是UINavigationController的子类再选中第一个TabBar,否则不处理
- 在android中如何用线程来更新UI
- 设计模式之Builder模式