图论3 1011

三角形

有一个等边三角形,在每条边上等距离画n个点,(顶点上不画,把每条边分成n+1段),在这3n个点中选取3个点作为新三角形的顶点,求所有不同三角形的面积和。

3n个点有各自的编号,两个三角形不同当且仅当选取编号集合不同,规定单位面积为边长每一段长度的等边三角形面积。

答案对1e9+7取模

1<=n<=1e9

题解

很容易分出两类:有两个点在同一边上,三点都在不同边。

1.记有两个点的边为底边。可以得到

$2*3\sum_{x=1}^{n-1}x(n-x)*\sum_{h=1}^{n}h$(顶点可以在两边选取,底边有三种

$3n(n+1)(n\sum_{x=1}^{n-1}x-\sum_{x=1}^{n-1}x^{2})$

$\frac{n^{2}(n+1)(n^{2}-1)}{2}$

2.在三边分别选边,记a,b,c为三点到所在边的左端点的距离

$\sum_{a=1}^{n}\sum_{b=1}^{n}\sum_{c=1}^{n}(n+1)^{2}-(n+1-a)b-(n+1-b)c-(n+1-c)a$

$\sum_{a=1}^{n}\sum_{b=1}^{n}\sum_{c=1}^{n}(n+1)^{2}-(n+1)(a+b+c)+ab+ac+bc$

$(n+1)^{2}$与a,b,c无关,所以可以算得贡献为$n^{3}(n+1){2}$

对于(a+b+c)可以考虑画出树形图,发现c从1-n的取值重复了$n^{2}$次,所以贡献为$\frac{n^{3}(n+1)^{2}}{2}$,a,b,c并无本质区别,所以a+b+c的贡献为$\frac{3n^{3}(n+1)^{2}}{2}$

对于后面剩下的部分只看$(a+b)c$

$(\sum_{a=1}^{n}\sum_{b=1}^{n}(a+b))*\sum_{c=1}^{n}c$

$\frac{n^{3}(n+1)^{2}}{2}$

对于$ab$可以用$\sum_{c=1}^{n}(\sum_{a=1}^{n}a*\sum_{b=1}^{n}b)$计算或者可以根据a,b,c无本质区别直接对刚才的$(a+b)c$*3/2即可

最后合并就是$\frac{n^{2}(n+1)(n^{2}-1)}{2}+\frac{n^{3}(n+1)^{2}}{4}$

#include<cstdio>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
const int mod=1000000007;
const ll inv2=500000004;
const ll inv4=250000002;
ll n;
ll ret=0,ans;

int main(){
    freopen("triangle.in","r",stdin);
    freopen("triangle.out","w",stdout);
    scanf("%lld",&n);
    ans=n*n%mod*(n+1)%mod*(n*n%mod-1)%mod*inv2%mod;//有两个点在一条边 
    ans=(ans+n*n%mod*n%mod*(n+1)%mod*(n+1)%mod*inv4%mod)%mod;
    printf("%lld",(ans%mod+mod)%mod);
}
triangle

速度限制

题目描述

题解

考虑到v很小而且通过道路时间和速度有关,所以直接把dis多开一维记录到达i点速度为j的时候的最小时间。

在最短路时,记录标点号和速度即可。可以看做分层图(按速度分层)。要求路径就直接记录前驱。

代码挺简单,但是一开始没想到方法...

#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;

const int maxn=155;
const int maxm=555;
const double inf=40000000000000000L;
int n,m,t;
int cnt,head[maxn];
double dis[maxn][maxm];
pair<int,int> pre[maxn][maxm];
int top,s[maxn];
struct edge{
    int x,y,v,l,next;
}e[maxn*maxn];

template<class T>inline void read(T &x){
    x=0;int f=0;char ch=getchar();
    while(!isdigit(ch)) {f|=(ch=='-');ch=getchar();}
    while(isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
    x = f ? -x : x ;
}

void add(int x,int y,int v,int l){
    e[++cnt]=(edge){x,y,v,l,head[x]};
    head[x]=cnt;
}

bool vis[maxn][maxm];
void spfa(){
    queue<pair<int,int> > q;
    memset(dis,0x7f,sizeof(dis));
    q.push(make_pair(0,70));
    vis[0][70]=true;dis[0][70]=0;
    while(!q.empty()){
        int x=q.front().first,nowv=q.front().second;
        q.pop();
        vis[x][nowv]=false;
        for(int i=head[x];i;i=e[i].next){
            int y=e[i].y;
            if(!e[i].v){//没限速 
                if(dis[y][nowv]>dis[x][nowv]+1.0*e[i].l/nowv){
                    dis[y][nowv]=dis[x][nowv]+1.0*e[i].l/nowv;
                    pre[y][nowv]=make_pair(x,nowv);
                    if(!vis[y][nowv]){
                        q.push(make_pair(y,nowv));
                        vis[y][nowv]=true;
                    }
                }
            }
            else {//限速 
                if(dis[y][e[i].v]>dis[x][nowv]+1.0*e[i].l/e[i].v){
                    dis[y][e[i].v]=dis[x][nowv]+1.0*e[i].l/e[i].v;
                    pre[y][e[i].v]=make_pair(x,nowv);
                    if(!vis[y][e[i].v]){
                        q.push(make_pair(y,e[i].v));
                        vis[y][e[i].v]=true;
                    }
                }
            }
        }
    }
}

int main(){
    freopen("speed.in","r",stdin);
    freopen("speed.out","w",stdout);
    read(n);read(m);read(t);
    for(int i=1;i<=m;i++){
        int x,y,v,l;
        read(x);read(y);read(v);read(l);
        add(x,y,v,l);
    }
    spfa();
    pair<int,int> x=make_pair(t,0);
    double mx=inf;
    for(int i=0;i<=500;i++)
     if(dis[t][i]<mx)
      mx=dis[t][i],x.second=i;
    while(1){
        s[++top]=x.first;
        if(!x.first) break;
        x=pre[x.first][x.second];
    }
    for(int i=top;i;i--) printf("%d ",s[i]);
}
speed

替换游戏

 题解

对于60%的数据,直接建返图缩点跑拓扑就好了

#include<queue>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long
const int maxn=100005;
int n,m,k,Q;
int cnt,head[maxn];
int d[maxn];
vector<int> g[maxn];
int cur,dfn[maxn],low[maxn];
bool flag[maxn];
int top,s[maxn];
int num,res[maxn],size[maxn];
struct edge{
    int x,y,next;
}e[maxn<<3];
ll f[maxn];

template<class T>inline void read(T &x){
    x=0;int f=0;char ch=getchar();
    while(!isdigit(ch)) {f|=(ch=='-');ch=getchar();}
    while(isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
    x = f ? -x : x ;
}

void add(int x,int y){
    e[++cnt]=(edge){x,y,head[x]};
    head[x]=cnt;d[y]++;
}

void tarjan(int x){
    dfn[x]=low[x]=++cur;
    flag[x]=true;s[++top]=x;
    for(unsigned int i=0;i<g[x].size();i++){
        int y=g[x][i];
        if(!dfn[y]){tarjan(y);low[x]=min(low[x],low[y]);}
        else if(flag[y]) low[x]=min(low[x],dfn[y]);
    }
    if(dfn[x]==low[x]){
        ++num;
        int t;
        do{
            t=s[top--];
            res[t]=num;
            flag[t]=false;
            size[num]+=t;
        }while(t!=x);
    }
}

void topsort(){
    queue<int> q;
    for(int i=1;i<=num;i++)
     if(!d[i]) q.push(i),f[i]=size[i];
    while(!q.empty()){
        int x=q.front();
        q.pop();
        for(int i=head[x];i;i=e[i].next){
            int y=e[i].y;
            if(f[y]<f[x]+size[y]) f[y]=f[x]+size[y];
            d[y]--;
            if(!d[y]) q.push(y);
        }
    }
}

void plana(){
    for(int i=1;i<=m;i++){
        int x,y;
        read(x);read(y);
        g[y].push_back(x);
    }
    for(int i=n;i>=k;i--) g[i].push_back(i-k);
    for(int i=0;i<=n;i++)
     if(!dfn[i]) tarjan(i);
    for(int i=0;i<=n;i++)
     for(unsigned int j=0;j<g[i].size();j++)
      if(res[i]!=res[g[i][j]]) add(res[i],res[g[i][j]]);
    topsort();
    read(Q);
    while(Q--){
        int x;read(x);
        printf("%lld\n",f[res[x]]);
    }
}

int main(){
    freopen("substitution.in","r",stdin);
    freopen("substitution.out","w",stdout);
    read(n);read(m);read(k);
    plana();
}
/*
11 3 12
1 10
10 1
11 10
*/
60

猜你喜欢

转载自www.cnblogs.com/sto324/p/11656427.html