CSU Monthly 2013 Oct.
2013-10-02 21:40
447 查看
题目:CSU Monthly
2013 Oct.
做了不到两个小时就打球去了。虽然没能坚持做完,但是感觉还不错。
A.Small
change
水题。好像就是之前看的关于一个面试题还是什么的。用尽量少的钞票来表示从1到n的值,那么想想二进制原理就知道了。所以这个水题求的是二进制的位数。
B.Scoop
water
数学题。裸的catalan。求C(2n,n) - C(2n,n+1) %mod
可以用Lucas定理求,不过mod太大好像没什么优化。直接暴力求逆元也能过。
C.CX‘s
dreams
标程说是最大权闭合子图。图论题,不会。
D.CX
and girls
最短路。wiking大神敲的。
E.ZZY‘s
new company
题解说是线段树+倍增法查找最近公共祖先,不会做。
F.ZZY
and his little friends
判断抑或的最大值是否大于m,字典树
G.Apple
tree
树形依赖背包,不会。
H.A
very hard problem
//数论题。。。还在做。。A了再把代码粘过来吧。
好吧。。。这题过不了。。。倍数问题很简单就是(x/p)*(y/p),约数的问题,方法是对p质因数分解之后求出p的所有约数,然后对每个约数的处理同 hdu 1695 稍微有点点不同,自己改下应该就ok,==,由于基本上不会莫比乌斯反演,我改了好久也改不对,pass吧。
I.The
contest
分组背包。小建建A了,贴个代码。
J.Scholarship
贪心,思维题。小建建先A了,我赛后A掉了。
2013 Oct.
做了不到两个小时就打球去了。虽然没能坚持做完,但是感觉还不错。
A.Small
change
水题。好像就是之前看的关于一个面试题还是什么的。用尽量少的钞票来表示从1到n的值,那么想想二进制原理就知道了。所以这个水题求的是二进制的位数。
#include <cstring> #include <iostream> #include <algorithm> #include <cmath> #include <cstdio> using namespace std; int main() { int n; while(scanf("%d",&n)!=EOF) { int ans=0; while(n) { n/=2; ans++; } printf("%d\n",ans); } return 0; }
B.Scoop
water
数学题。裸的catalan。求C(2n,n) - C(2n,n+1) %mod
可以用Lucas定理求,不过mod太大好像没什么优化。直接暴力求逆元也能过。
#include <cstring> #include <iostream> #include <algorithm> #include <cmath> #include <cstdio> using namespace std; #define mod 1000000007 #define maxn 20010 const long long p=mod; long long fac[maxn]; long long Pow(long long a,long long b,long long Mod) { long long ans=1; while(b) { if(b&1) { b--; ans=(ans*a)%Mod; } else { b/=2; a=(a*a)%Mod; } } return ans; } void init() { fac[0]=1; for(int i=1;i<maxn;i++) fac[i]=fac[i-1]*i%p; } long long c(long long n,long long m) { if(n<m) return 0; long long ans=fac *Pow(fac[n-m]*fac[m]%p,p-2,p)%p; return ans; } long long Lucas(long long n,long long m) { if(m==0) return 1; return Lucas(n/p,m/p)*c(n%p,m%p)%p; } long long solve(int n) { long long ans=c(2*n,n)-c(2*n,n+1); return (ans%mod+mod)%mod; } int main() { init(); int n; while(scanf("%d",&n)!=EOF) { printf("%lld\n",solve(n)%mod); } return 0; }
C.CX‘s
dreams
标程说是最大权闭合子图。图论题,不会。
D.CX
and girls
最短路。wiking大神敲的。
// wiking #include<cstdio> #include<cstring> #include<algorithm> #include<vector> #include<map> #include<cmath> #include<queue> #include<iostream> using namespace std; const int maxn = 10000 + 5; const int INF = 1000000000; typedef long long LL; typedef pair<int,int> P; int n,m; struct Edge{ int from,to,dis; }e[maxn*2]; int d[maxn]; int vis[maxn]; vector<Edge> G[maxn]; void Dij(int x){ priority_queue<P,vector<P>,greater<P> > Q; memset(vis,0,sizeof(vis)); for(int i = 0;i <= n;i++) d[i] = INF; Q.push(P(0,x)); while(!Q.empty()){ P p = Q.top();Q.pop(); int id = p.second; LL dis = p.first; if(vis[id] == 1) continue; vis[id] = 1; d[id] = dis; for(int i = 0;i < G[id].size();i++){ Edge edgs = G[id][i]; int to = edgs.to; LL der = edgs.dis; if(d[to] > d[id] + der){ d[to] = d[id] + der; Q.push(P(d[to],to)); } } } } int a[maxn]; int dp[maxn]; int dfs(int x){ if(dp[x] != -1) return dp[x]; if(x == 1) return dp[x] = a[x]; int Max = 0; for(int i = 0;i < G[x].size();i++){ Edge edges = G[x][i]; int to = edges.to; int dis = edges.dis; if(d[to]+dis == d[x]) Max = max(Max,dfs(to)); } return dp[x] = a[x]+Max; } int main(){ while(scanf("%d%d",&n,&m) != EOF){ for(int i = 0;i <= n;i++) G[i].clear(); for(int i = 1;i <= n;i++){ scanf("%d",&a[i]); } for(int i = 0;i < m;i++){ scanf("%d%d%d",&e[i].from,&e[i].to,&e[i].dis); e[i+m].from = e[i].to;e[i+m].to = e[i].from;e[i+m].dis = e[i].dis; G[e[i].from].push_back(e[i]); G[e[i].to].push_back(e[i+m]); } Dij(1); if(d == INF){ printf("-1\n"); continue; } memset(dp,-1,sizeof(dp)); printf("%d\n",dfs(n)); } return 0; }
E.ZZY‘s
new company
题解说是线段树+倍增法查找最近公共祖先,不会做。
F.ZZY
and his little friends
判断抑或的最大值是否大于m,字典树
#include <stdio.h> #include <string.h> #define MAX(a,b) ((a)>(b)?(a):(b)) #define NODE 3200010 #define N 100010 int n; int v ; int node; int next[NODE][2]; int end[NODE]; void add(int cur,int k) { memset(next[node],0,sizeof(next[node])); end[node]=0; next[cur][k]=node++; } int cal(int x) { int i,k,cur=0; for(i=30;i>=0;i--) { k=((1<<i)&x)?0:1; if(next[cur][k]) cur=next[cur][k]; else cur=next[cur][1-k]; } return (x^end[cur]); } int main() { int i,j,k,x,cur; long long ans; long long mm; while(~scanf("%d%lld",&n,&mm)) { node=1; memset(next[0],0,sizeof(next[0])); for(i=0;i<n;i++) { scanf("%d",&x); v[i]=x; cur=0; for(j=30;j>=0;j--) { k=((1<<j)&x)?1:0; if(next[cur][k]==0) add(cur,k); cur=next[cur][k]; } end[cur]=x; } for(ans=i=0;i<n;i++) ans=MAX(ans,cal(v[i])); if(ans>mm) printf("YES\n"); else printf("NO\n"); } return 0; }
G.Apple
tree
树形依赖背包,不会。
H.A
very hard problem
//数论题。。。还在做。。A了再把代码粘过来吧。
好吧。。。这题过不了。。。倍数问题很简单就是(x/p)*(y/p),约数的问题,方法是对p质因数分解之后求出p的所有约数,然后对每个约数的处理同 hdu 1695 稍微有点点不同,自己改下应该就ok,==,由于基本上不会莫比乌斯反演,我改了好久也改不对,pass吧。
I.The
contest
分组背包。小建建A了,贴个代码。
#include<stdio.h> #include<string.h> #include<algorithm> #include<map> #include<vector> using namespace std; int p[1011]; int find(int x) { if(p[x]!=x) return p[x]=find(p[x]); return x; } int dp[1011]; int n,Wmax,k,a,b; int P[1011],W[1011]; map<int,int>root; vector<int>e[1011]; int main() { while(~scanf("%d%d%d",&n,&Wmax,&k)) { int r=1; root.clear(); for(int i=1;i<=n;i++) p[i]=i,e[i].clear(); for(int i=1;i<=n;i++) scanf("%d%d",&P[i],&W[i]); for(int i=1;i<=k;i++) { scanf("%d%d",&a,&b); int A=find(a),B=find(b); if(p[A]!=B) p[A]=B; } for(int i=1;i<=n;i++) { int x=find(i); if(root[x]==0) root[x]=r++; e[root[x]].push_back(i); } // printf("%d %d\n",e[1][0],e[1][1]); memset(dp,0,sizeof(dp)); for(int i=1;i<r;i++) for(int v=Wmax;v>=0;v--) for(int j=0;j<e[i].size();j++) { int x=e[i][j]; if(v<W[x]) continue; dp[v]=max(dp[v],dp[v-W[x]]+P[x]); } printf("%d\n",dp[Wmax]); } }
J.Scholarship
贪心,思维题。小建建先A了,我赛后A掉了。
// 小建建 #include<stdio.h> #include<string.h> #include<algorithm> using namespace std; int n; int main() { scanf("%d",&n); while(n--) { char s[12],s1[12]; char ans[12]; int b; scanf("%d",&b); if(b<0) { printf("0\n"); continue; } b++; int l=0; while(b) { s1[l++]=b%10+'0'; b/=10; } s1[l]='\0'; l=strlen(s1); for(int i=0;i<l;i++) { s[l-1-i]=s1[i]; } s[l]='\0'; //printf("%s z\n",s); if(l==1) { printf("%s\n",s); } else { while(1) { int tag=-1; for(int i=1;s[i];i++) { if(s[i]!='0'&&s[i]==s[i-1]) { tag=i;break; } } if(tag==-1) { printf("%s\n",s); break; } int r,a=1; for(int i=tag+1;s[i];i++) s[i]='0'; for(int i=tag;i>=0;i--) { a+=s[i]-'0'; if(a<=9) { r=0; s[i]=a+'0';break; } else { r=1; s[i]=a%10+'0'; a/=10; } } if(r) { ans[0]='1'; for(int i=0;s[i];i++) ans[i+1]=s[i]; ans[l+1]='\0'; } else { for(int i=0;s[i];i++) ans[i]=s[i]; ans[l]='\0'; } strcpy(s,ans); } } } return 0; }
// mine #include <cstring> #include <iostream> #include <cmath> #include <algorithm> #include <cstdio> #include <strstream> using namespace std; int main() { int t; cin>>t; while(t--) { int i; string s=""; int num; cin>>num; if(num<0) { printf("0\n"); continue; } if(num==0) { printf("1\n"); continue; } num++; strstream ss; ss << num; ss >> s; int cnt=s.size()-1; bool pika=true; while(pika){ int index=s.size(); for(i=1;i<s.size();i++) { if(s[i]==s[i-1] && s[i]!='0') { index=i; break; } } if(index==s.size()) { cout<<s<<endl; pika=false; continue; } cnt=index; int remain=1; bool ok=false; while(cnt>=0) { if(s[cnt]=='9' && remain==1) { if(cnt==0) ok=true; s[cnt]='0'; cnt--; } else if(remain) { s[cnt]++; remain=0; cnt--; } else break; } for(int i=index+1;i<s.size();i++) s[i]='0'; if(ok) { s="1"+s; } } } return 0; }
相关文章推荐
- C++/C功能程序代码
- assert
- UVa 11875 Brick Game (water ver.)
- 构造函数为什么不能为虚函数
- JAVA泛型类和泛型方法
- 第二章例2-8
- Hdu4767 Bell (贝尔数 中国剩余定理 构造矩阵)
- Java语法基础
- 从一个表整行复制数据到另一个表
- ZOJ 2392 The Counting Problem(模拟)
- 使IRB语法高亮方法的办法
- JavaScript入门
- Unity3D--day03
- TCP 和 UDP 传输的深入浅析,MSN 和 QQ 文件传输速度解析
- HDU 3336 KMP_NEXT
- 第二章5
- cocos2d-x精灵的放大和缩小
- 推广方式杂记
- HashMap与Hashtable的区别
- android系统图标的使用