zoukankan      html  css  js  c++  java
  • Forethought Future Cup

    A.最长不会超过a的个数的两倍-1。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<iostream>
     4 #include<algorithm>
     5 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
     6 typedef long long ll;
     7 using namespace std;
     8 
     9 const int N=100;
    10 int n,d;
    11 char s[N];
    12 
    13 int main(){
    14     scanf("%s",s+1); n=strlen(s+1);
    15     rep(i,1,n) if (s[i]=='a') d++;
    16     printf("%d
    ",min(d*2-1,n));
    17     return 0;
    18 }
    View Code

    B.删除所有a后一定是两个完全相同的串接起来。

     1 #include<string>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<iostream>
     5 #include<algorithm>
     6 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
     7 typedef long long ll;
     8 using namespace std;
     9 
    10 string s,t;
    11 
    12 int main(){
    13     cin>>s; int l=s.length();
    14     rep(i,0,l-1) if (s[i]!='a') t+=s[i];
    15     if (t.length()&1){ puts(":("); return 0; }
    16     int p=t.length()/2;
    17     string t1=t.substr(0,p),t2=t.substr(p,p);
    18     if (t1==t2 && t1==s.substr(s.length()-p,p)) cout<<s.substr(0,s.length()-p)<<endl;
    19         else  puts(":(");
    20     return 0;
    21 }
    View Code

    C.一种方法是直接二进制分组,能处理图的情况。

    另一种是回顾一种树上找直径的方法,先任选一个点u找到离它最远的一个点v,再从v开始找到离它最远的点w,v到w就是直径。

    这道题先任选u,然后通过二分点集找到最远点v,再一次查询即可得到直径。

     1 #include<string>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<iostream>
     5 #include<algorithm>
     6 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
     7 typedef long long ll;
     8 using namespace std;
     9 
    10 string s,t;
    11 
    12 int main(){
    13     cin>>s; int l=s.length();
    14     rep(i,0,l-1) if (s[i]!='a') t+=s[i];
    15     if (t.length()&1){ puts(":("); return 0; }
    16     int p=t.length()/2;
    17     string t1=t.substr(0,p),t2=t.substr(p,p);
    18     if (t1==t2 && t1==s.substr(s.length()-p,p)) cout<<s.substr(0,s.length()-p)<<endl;
    19         else  puts(":(");
    20     return 0;
    21 }
    方法一

    F.有多种做法,我的f[i][0/1/2]表示以i为根的子树中,所有叶子(包括根)都已经被确定分到某集合中/存在叶子未被划分集合(它们将和i以上的点配对)/所有叶子都已划分但根不属于任何一个集合,的方案数。转移显然,主要关注初始值的设定,叶子和非叶节点是不一样的。

     1 #include<cstdio>
     2 #include<algorithm>
     3 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
     4 #define For(i,x) for (int i=h[x],k; i; i=nxt[i])
     5 using namespace std;
     6 
     7 const int N=200010,mod=998244353;
     8 int n,cnt,fa[N],f[N][3],h[N],to[N],nxt[N];
     9 
    10 void add(int u,int v){ to[++cnt]=v; nxt[cnt]=h[u]; h[u]=cnt; }
    11 
    12 void dfs(int x){
    13     if (!h[x]){ f[x][1]=f[x][2]=1; return; }
    14     f[x][2]=1;
    15     For(i,x){
    16         dfs(k=to[i]);
    17         f[x][0]=(1ll*f[x][0]*(f[k][0]+f[k][2])+1ll*f[x][1]*f[k][1])%mod;
    18         f[x][1]=(1ll*(f[x][1]+f[x][2])*f[k][1]+1ll*f[x][1]*(f[k][0]+f[k][2]))%mod;
    19         f[x][2]=1ll*f[x][2]*(f[k][0]+f[k][2])%mod;
    20     }
    21 }
    22 
    23 int main(){
    24     scanf("%d",&n);
    25     rep(i,2,n) scanf("%d",&fa[i]),add(fa[i],i);
    26     dfs(1); printf("%d
    ",(f[1][0]+f[1][2])%mod);
    27     return 0;
    28 }
    View Code

    G.每个建筑拆成h+1个点分别代表它的高度为[0,h],第i-1个点向第i个点连流量为h^2-i^2的边,第h个点向T连流量无穷的边。对于每个询问,将[l,r]中的代表高度h的点全部连向一个新点,流量无穷,再从新点向T连流量为c的边。n*h*h-最小割就是最终答案。

     1 #include<cstdio>
     2 #include<algorithm>
     3 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
     4 #define For(i,x) for (int i=h[x],k; i; i=nxt[i])
     5 using namespace std;
     6 
     7 const int N=10010,inf=1e9;
     8 int n,H,m,S,T,l,r,x,c,ans,q[N],cur[N],d[N],cnt=1,h[N],to[N],nxt[N],fl[N];
     9 
    10 int F(int i,int j){ return (i-1)*(H+1)+j+1; }
    11 
    12 void add(int u,int v,int w){
    13     to[++cnt]=v; fl[cnt]=w; nxt[cnt]=h[u]; h[u]=cnt;
    14     to[++cnt]=u; fl[cnt]=0; nxt[cnt]=h[v]; h[v]=cnt;
    15 }
    16 
    17 bool bfs(){
    18     rep(i,1,T+m) d[i]=0; d[S]=1; q[1]=S;
    19     for (int st=0,ed=1; st!=ed; ){
    20         int x=q[++st];
    21         For(i,x) if (fl[i] && !d[k=to[i]])
    22             d[k]=d[x]+1,q[++ed]=k;
    23     }
    24     return d[T];
    25 }
    26 
    27 int dfs(int x,int lim){
    28     if (x==T) return lim;
    29     int c=0;
    30     for (int &i=cur[x],k; i; i=nxt[i])
    31         if (fl[i] && d[k=to[i]]==d[x]+1){
    32             int t=dfs(k,min(lim-c,fl[i]));
    33             c+=t; fl[i]-=t; fl[i^1]+=t;
    34             if (c==lim) return c;
    35         }
    36     if (!c) d[x]=-1;
    37     return c;
    38 }
    39 
    40 int main(){
    41     scanf("%d%d%d",&n,&H,&m); S=F(n,H)+1; T=S+1;
    42     rep(i,1,n){
    43         add(S,F(i,0),H*H);
    44         rep(j,1,H) add(F(i,j-1),F(i,j),H*H-j*j);
    45         add(F(i,H),T,inf);
    46     }
    47     rep(i,1,m){
    48         scanf("%d%d%d%d",&l,&r,&x,&c);
    49         rep(j,l,r) add(F(j,x),T+i,inf);
    50         add(T+i,T,c);
    51     }
    52     while (bfs()){
    53         rep(i,1,T+m) cur[i]=h[i];
    54         ans+=dfs(S,inf);
    55     }
    56     printf("%d
    ",n*H*H-ans);
    57     return 0;
    58 }
    View Code

    H.显然就是求五个点的凸包个数。一个方法是枚举上顶点,将所有点按相对于它的极角排序,再枚举第3,4个点,第2,5个点就是前缀后缀中满足某条件的点的个数,树状数组在线统计一下即可。$O(n^3log n)$

    另一个方法是f[i][j][k(0..5)]表示第一个点为i,当前确定了k条边,最后一个点是j,的方案数。将所有边按斜率排序,然后跑类似Bellman-Ford即可。$O(n^3)$

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<algorithm>
     4 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
     5 typedef long long ll;
     6 using namespace std;
     7 
     8 const int N=310;
     9 int n,tot;
    10 ll ans,f[N][N][6];
    11 struct P{ int x,y; }p[N];
    12 struct L{ P x; int a,b; }e[N*N];
    13 
    14 P operator -(const P &a,const P &b){ return (P){a.x-b.x,a.y-b.y}; }
    15 P operator +(const P &a,const P &b){ return (P){a.x+b.x,a.y+b.y}; }
    16 ll operator *(const P &a,const P &b){ return 1ll*a.x*b.y-1ll*b.x*a.y; }
    17 bool operator <(const P &a,const P &b){ return a*b<0; }
    18 bool operator <(const L &a,const L &b){
    19     if (a.x<b.x) return 1;
    20     if (b.x<a.x) return 0;
    21     return a.a==b.a ? a.b<b.b : a.a<b.a;
    22 }
    23 
    24 int main(){
    25     scanf("%d",&n);
    26     rep(i,1,n) scanf("%d%d",&p[i].x,&p[i].y);
    27     rep(i,1,n) rep(j,1,n) if (i!=j) e[++tot]=(L){p[j]-p[i],i,j};
    28     sort(e+1,e+tot+1);
    29     rep(i,1,tot){
    30         int u=e[i].a,v=e[i].b; f[u][v][1]++;
    31         rep(i,1,5) rep(j,1,n) f[j][v][i+1]+=f[j][u][i];
    32     }
    33     rep(i,1,n) ans+=f[i][i][5];
    34     cout<<ans<<endl;
    35     return 0;
    36 }
    方法二
  • 相关阅读:
    我的2007, 兼谈些对技术的看法
    回帖整理: 关于"学习Java社区"更清晰的思路
    回帖整理: 创业心态
    我的世界观 by 爱因斯坦
    回帖整理: 论团队中的设计工作
    请大家帮我一个忙
    回帖整理: Java社区有什么可学的?
    SSL原理及应用(1)SSL协议体系结构
    文件和目录的访问控制(4) 审核规则
    强名称(2)引用强名称签名的程序集
  • 原文地址:https://www.cnblogs.com/HocRiser/p/10792296.html
Copyright © 2011-2022 走看看