【一场模拟赛?】
JSH师兄来讲课,于是也弄了场比赛给我们做。。。被虐。。。
A.简单的图论题
嗯求一个拓扑图中每个点的可达点数量,n=10000
嗯记忆化搜索,但是有可能搜到重复的点,于是我们不搜索可达点数量,转成搜索可达点集,这个可以用一个bool数组记录。
于是STL有某种东西叫做bitset(长知识
// Problem#: 14938 // Submission#: 3794800 // The source code is licensed under Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License // URI: http://creativecommons.org/licenses/by-nc-sa/3.0/ // All Copyright reserved by Informatic Lab of Sun Yat-sen University #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <cctype> #define rep(i, l, r) for(int i=l; i<=r; i++) #define down(i, l, r) for(int i=l; i>=r; i--) #define clr(x, c) memset(x, c, sizeof(x)) #define travel(x) for(edge *p=fir[x]; p; p=p->n) #define maxn 10009 #define maxm 50009 #define inf 0x7fffffff #define Q 1000000007 #define ll long long using namespace std; int read() { int x=0, f=1; char ch=getchar(); while (!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();} while (isdigit(ch)) x=x*10+ch-'0', ch=getchar(); return x*f; } struct edge{int y; edge *n;} e[maxm], *fir[maxn], *pt=e; void AddE(int x, int y){pt->y=y, pt->n=fir[x], fir[x]=pt++;} int n, m, f[maxn]; ll b[maxn][200]; bool v[maxn]; void dfs(int x) { v[x]=1; b[x][x/50]=(ll)1<<(x%50); travel(x) if (!v[p->y]) dfs(p->y); travel(x) rep(i, 0, 199) b[x][i]|=b[p->y][i]; } void Init(){clr(fir, 0); pt=e; clr(f, 0); clr(v, 0);} int main() { int t=read(); while (t--) { n=read(), m=read(); Init(); rep(i, 1, m){int x=read(), y=read(); AddE(x, y);} rep(i, 0, n-1) if (!v[i]) dfs(i); rep(i, 0, n-1) rep(j, 0, 199) { while (b[i][j]) f[i]+=b[i][j]&1, b[i][j]>>=1; } rep(i, 0, n-1) printf("%d%c", f[i], i==(n-1)?'\n':' '); } return 0; }
B.最大价值
懒得说题目。。。
贪心+排序后Dp
#include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <cctype> #define rep(i, l, r) for(int i=l; i<=r; i++) #define down(i, l, r) for(int i=l; i>=r; i--) #define clr(x, c) memset(x, c, sizeof(x)) #define travel(x) for(edge *p=fir[x]; p; p=p->n) #define maxn 10009 #define inf 0x7fffffff #define ll long long using namespace std; int read() { int x=0, f=1; char ch=getchar(); while (!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();} while (isdigit(ch)) x=x*10+ch-'0', ch=getchar(); return x*f; } struct node{double a,b;} q[maxn]; bool cmp(node a, node b){return a.a/(a.b-1)>b.a/(b.b-1);} int n, k; double f[25][maxn]; int main() { int t=read(); while (t--) { n=read(); k=read(); rep(i, 1, n) scanf("%lf%lf", &q[i].a, &q[i].b); sort(q+1, q+1+n, cmp); clr(f, 0); rep(i, 1, k) { double m=0; rep(j, 1, n) f[i][j]=m*q[j].b+q[j].a, m=max(m, f[i-1][j]); } double ans=0; rep(i, 1, n) ans=max(ans, f[k][i]); printf("%.2lf\n", ans); } return 0; }
C.选择
水题
#include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <cctype> #define rep(i, l, r) for(int i=l; i<=r; i++) #define clr(x, c) memset(x, c, sizeof(x)) #define travel(x) for(edge *p=fir[x]; p; p=p->n) #define maxn 1000009 #define Q 1000000 #define inf 0x7fffffff #define ll long long using namespace std; int read() { int x=0, f=1; char ch=getchar(); while (!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();} while (isdigit(ch)) x=x*10+ch-'0', ch=getchar(); return x*f; }/* struct edge{int y; edge *n;} e[maxm], *fir[maxn], *pt=e; void AddE(int x, int y){pt->y=y, pt->n=fir[x]; fir[x]=pt++;} */ int c[maxn]; bool b[maxn]; int main() { b[1]=1; rep(i, 1, (int)sqrt(Q)) if (!b[i]) for(int a=i+i; a<=Q; a+=i) b[a]=1; int a=0; rep(i, 1, Q) if (!b[i]) c[i]=++a; for(int w=read(); w>0; w=read()) printf("%d\n", c[w]); return 0; }
D.寻找第K小
a数组和b数组先从小到大排序
二分答案ans,然后每行都二分查找有多少个小于ans的值。两个log
或者不二分查找了,直接从右上角走到左下角。
#include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <cctype> #define rep(i, l, r) for(int i=l; i<=r; i++) #define clr(x, c) memset(x, c, sizeof(x)) #define travel(x) for(edge *p=fir[x]; p; p=p->n) #define maxn 20009 #define inf 0x7fffffff #define ll long long using namespace std; int read() { int x=0, f=1; char ch=getchar(); while (!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();} while (isdigit(ch)) x=x*10+ch-'0', ch=getchar(); return x*f; }/* struct edge{int y; edge *n;} e[maxm], *fir[maxn], *pt=e; void AddE(int x, int y){pt->y=y, pt->n=fir[x]; fir[x]=pt++;} */ int n, m, k; ll c[maxn], d[maxn]; bool can(ll x) { int now=0; rep(i, 1, n) { int l=0, r=m, mid; while (l<r) { mid=((l+r)>>1)+1; if (c[i]*d[mid]>=x) r=mid-1; else l=mid; } now+=l; if (now>k-1) return 1; } return 0; } int main() { int t=read(); while (t--) { n=read(), m=read(); k=read(); rep(i, 1, n) c[i]=read(); sort(c+1, c+1+n); rep(i, 1, m) d[i]=read(); sort(d+1, d+1+m); ll L=1, R=0xDE0B6B3A7640000; while (L<R) { ll mid=((L+R)>>1)+1; if (can(mid)) R=mid-1; else L=mid; } printf("%lld\n", L); } return 0; }
E.最强密码
好题!(百度之星的原题Orz
嗯先处理出含有a-z的块的个数,ans既是块数+1
然后记忆化搜索+剪纸(具体看程序把
#include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <cctype> #define rep(i, l, r) for(int i=l; i<=r; i++) #define down(i, l, r) for(int i=l; i>=r; i--) #define clr(x, c) memset(x, c, sizeof(x)) #define travel(x) for(edge *p=fir[x]; p; p=p->n) #define maxn 100009 #define inf 0x7fffffff #define Q 1000000007 #define ll long long using namespace std; int read() { int x=0, f=1; char ch=getchar(); while (!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();} while (isdigit(ch)) x=x*10+ch-'0', ch=getchar(); return x*f; } int l, a, tot, st[4009], c[maxn][26]; ll all, p[4009], f[4009][26]; char s[maxn]; bool b[26]; ll dfs(int k, int x, int y) { if (k==0) return 1; if (x<=st[k]) return p[k]; if (k!=a+1 && f[k][y]) return f[k][y]; int now=0; rep(i, 0, 25) if (c[x][i]) now=(now+dfs(k-1, c[x][i], i))%Q; return f[k][y]=now; } int main() { p[0]=1; rep(i, 1, 4000) p[i]=p[i-1]*26%Q; int t=read(), Case=0; while (t--) { scanf("%s", s); l=strlen(s); Case++; clr(c, 0); down(i, l-1, 0) { rep(j, 0, 25) c[i][j]=c[i+1][j]; c[i][s[i]-'a']=i+1; } clr(st, 0); tot=26; clr(b, 0); a=0; down(i, l-1, 0) { if (!b[s[i]-'a']) tot--; b[s[i]-'a']=1; if (!tot) a++, clr(b, 0), tot=26, st[a]=i; } st[a+1]=-1; clr(f, 0); printf("Case #%d:\n%d %lld\n", Case, a+1, (p[a+1]-dfs(a+1, 0, 0)+Q)%Q); } return 0; }
于是乎依旧被虐得很惨QAQ