考前冲刺 1

思路:矩阵优化数列

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
long long n,a,b;
long long t[2][2],ans[2][2],r[2][2];
void mul(long long a[2][2],long long b[2][2]){
    memset(r,0,sizeof(r));
    for(int i=0;i<2;i++)
        for(int j=0;j<2;j++)
            for(int k=0;k<2;k++)
                r[i][j]+=a[i][k]*b[k][j],r[i][j]%=7;
    for(int i=0;i<2;i++)
        for(int j=0;j<2;j++)
            a[i][j]=r[i][j];
}
int main(){
    freopen("attack.in","r",stdin);
    freopen("attack.out","w",stdout);
    scanf("%lld%lld%lld",&a,&b,&n);
    t[0][0]=a;t[0][1]=1;
    t[1][0]=b;
    ans[0][0]=1;ans[0][1]=1;
    if(n==2||n==1){ cout<<"1";return 0; }
    n-=2;
    while(n){
        if(n&1)    mul(ans,t);
        mul(t,t);
        n>>=1;
    }
    printf("%d",ans[0][0]);
}
View Code

 

 

思路:组合数学,把它拓展成一个二维平面的问题后,把物理老师看成是移动(1,0)生物老师看成是移动(0,1),那么到达(n,m)这个点。而且路线不经过对角线上方的路线总数就是答案。

 然后发现这和一个问题很像,部分分可以用卡特兰数去搞一下,原理戳这里或者这里

然后发现这还是一个组合数问题:对方向编号,向上是0,向右是1,那么从左下角走到右上角一定要经过M 个1和N个0。这个题目可以转化为从M+N个盒子中挑出M个盒子有多少种方法。

那么在不考虑对角线的情况下答案为C(m+n,m)。但是现在题目要求不能到达对角线上方,所以我们还需要减去经过对角线的上方的方案数。

 

原理戳这里的第三问

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int T,n,m;
int main(){
    freopen("fseq.in","r",stdin);
    freopen("fseq.out","w",stdout);
    scanf("%d",&T);
    while(T--){
        scanf("%d%d",&n,&m);
        if(m>n){ cout<<"0.000000"<<endl;continue; }
        else printf("%.6lf\n",1.0-m*1.0/(n+1)*1.0);
    }
}

 

 

思路:首先tarjin缩点,然后跑连边dfs找出树的直径的两个端点A,B,答案就是max(dis(x,a),dis(x,b))

#include<map>
#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define M 20010
#define MAXN 200010
using namespace std;
queue<int>que;
map<int,int>ma[M];
int n,m,tim;
int tot=1,tot1;
int top,sumcol;
int vis[M],visstack[M];
int col[M],dis[M],ans[M];
int dfn[M],low[M],stack[M];
int to[MAXN*2],net[MAXN*2],cap[MAXN*2],head[M];
int to1[MAXN*2],net1[MAXN*2],cap1[MAXN*2],head1[M];
void add(int u,int v,int w){
    to[++tot]=v;cap[tot]=w;net[tot]=head[u];head[u]=tot;
    to[++tot]=u;cap[tot]=w;net[tot]=head[v];head[v]=tot;
}
void add1(int u,int v,int w){
    to1[++tot1]=v;cap1[tot1]=w;net1[tot1]=head1[u];head1[u]=tot1;
    to1[++tot1]=u;cap1[tot1]=w;net1[tot1]=head1[v];head1[v]=tot1;
}
void tarjin(int now){
    low[now]=dfn[now]=++tim;
    stack[++top]=now;
    visstack[now]=1;
    for(int i=head[now];i;i=net[i]){
        if(vis[i]||vis[i^1])    continue;
        vis[i]=vis[i^1]=1;
        if(visstack[to[i]])
            low[now]=min(low[now],dfn[to[i]]);
        else if(!dfn[to[i]]){
            tarjin(to[i]);
            low[now]=min(low[now],low[to[i]]);
        }
    }
    if(low[now]==dfn[now]){
        sumcol++;
        col[now]=sumcol;
        while(stack[top]!=now){
            col[stack[top]]=sumcol;
            visstack[stack[top]]=0;
            top--;
        }
        visstack[now]=0;
        top--;
    }
}
void spfa(int s){
    memset(vis,0,sizeof(vis));
    memset(dis,0,sizeof(dis));
    while(!que.empty())    que.pop();
    que.push(s);
    vis[s]=1;dis[s]=0;
    while(!que.empty()){
        int now=que.front();
        que.pop();
        ans[s]=max(ans[s],dis[now]);
        for(int i=head1[now];i;i=net1[i])
            if(dis[to1[i]]<dis[now]+cap1[i]){
                dis[to1[i]]=dis[now]+cap1[i];
                if(!vis[to1[i]]){
                    vis[to1[i]]=1;
                    que.push(to1[i]);
                }
            }
    }
}
int main(){
    freopen("prize.in","r",stdin);
    freopen("prize.out","w",stdout);
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++){
        int u,v,w;
        scanf("%d%d%d",&u,&v,&w);
        add(u,v,w);
    }
    for(int i=1;i<=n;i++)
        if(!dfn[i])
            tarjin(i);
    for(int i=1;i<=n;i++)
        for(int j=head[i];j;j=net[j])
            if(col[i]!=col[to[j]])
                if(ma[col[i]].find(col[to[j]])==ma[col[i]].end()){
                    ma[col[i]][col[to[j]]]=1;
                    ma[col[to[j]]][col[i]]=1;
                    add1(col[i],col[to[j]],cap[j]); 
                }
    for(int i=1;i<=sumcol;i++)    spfa(i);
    for(int i=1;i<=n;i++)
        cout<<ans[col[i]]<<endl;
}
/*
6 6
1 4 2
1 2 6
2 5 3
2 3 7
6 3 4
3 1 8
*/
40分暴力
#include<map>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define M 20010
#define MAXN 200010
using namespace std;
map<int,int>ma[M];
int n,m,tim;
int tot=1,tot1,root;
int top,maxn,sumcol;
int visstack[M];
int col[M],dis[M],dis1[M];
int dfn[M],low[M],stack[M];
int to[MAXN*2],net[MAXN*2],cap[MAXN*2],head[M];
int to1[MAXN*2],net1[MAXN*2],cap1[MAXN*2],head1[M];
void add(int u,int v,int w){
    to[++tot]=v;cap[tot]=w;net[tot]=head[u];head[u]=tot;
    to[++tot]=u;cap[tot]=w;net[tot]=head[v];head[v]=tot;
}
void add1(int u,int v,int w){
    to1[++tot1]=v;cap1[tot1]=w;net1[tot1]=head1[u];head1[u]=tot1;
    to1[++tot1]=u;cap1[tot1]=w;net1[tot1]=head1[v];head1[v]=tot1;
}
void tarjin(int now,int fa){
    low[now]=dfn[now]=++tim;
    stack[++top]=now;
    visstack[now]=1;
    for(int i=head[now];i;i=net[i])
        if(visstack[to[i]]&&to[i]!=fa)
            low[now]=min(low[now],dfn[to[i]]);
        else if(!dfn[to[i]]){
            tarjin(to[i],now);
            low[now]=min(low[now],low[to[i]]);
        }
    if(low[now]==dfn[now]){
        sumcol++;
        col[now]=sumcol;
        while(stack[top]!=now){
            col[stack[top]]=sumcol;
            visstack[stack[top]]=0;
            top--;
        }
        visstack[now]=0;
        top--;
    }
}
void dfs(int now,int fa){
    for(int i=head1[now];i;i=net1[i])
        if(to1[i]!=fa){
            dis[to1[i]]=dis[now]+cap1[i];
            if(dis[to1[i]]>maxn)    maxn=dis[to1[i]],root=to1[i];
            dfs(to1[i],now);
        }
}
void dfs1(int now,int fa){
    for(int i=head1[now];i;i=net1[i])
        if(to1[i]!=fa){
            dis1[to1[i]]=dis1[now]+cap1[i];
            dfs1(to1[i],now);
        }
}
int main(){
    freopen("prize.in","r",stdin);
    freopen("prize.out","w",stdout);
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++){
        int u,v,w;
        scanf("%d%d%d",&u,&v,&w);
        add(u,v,w);
    }
    for(int i=1;i<=n;i++)
        if(!dfn[i])
            tarjin(i,0);
    for(int i=1;i<=n;i++)
        for(int j=head[i];j;j=net[j])
            if(col[i]!=col[to[j]])
                if(ma[col[i]].find(col[to[j]])==ma[col[i]].end()){
                    ma[col[i]][col[to[j]]]=1;
                    ma[col[to[j]]][col[i]]=1;
                    add1(col[i],col[to[j]],cap[j]); 
                }
    dfs(1,-1);
    maxn=0;
    memset(dis,0,sizeof(dis));
    dfs(root,-1);
    maxn=0;
    dfs1(root,-1);
    for(int i=1;i<=n;i++)
        cout<<max(dis[col[i]],dis1[col[i]])<<endl;
}
/*
6 6
1 4 2
1 2 6
2 5 3
2 3 7
6 3 4
3 1 8
*/

 

posted @ 2017-11-07 16:24  一蓑烟雨任生平  阅读(176)  评论(0编辑  收藏  举报