11.7模拟赛

T1找循环节

循环节的大小一定在49之内(7*7)

读入int,挂成55

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <string>

using namespace std;
const int N = 1000000;

#define LL long long

LL f[N];
LL n, A, B, js, bi1, bi2;

inline LL read(){
    LL x = 0; char c = getchar();
    while(c < '0' || c > '9') c = getchar();
    while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
    return x; 
}int main()
{
    freopen("attack.in", "r", stdin);
    freopen("attack.out", "w", stdout);
    A = read();
    B = read();
    n = read();
    bi1 = (A + B) % 7;
    bi2 = (A * bi1 + B) % 7;
    f[1] = f[2] = 1;
    f[3] = bi1;
    f[4] = bi2;
    for(int i = 5; ; i ++){
        f[i] = (A * f[i - 1] + B * f[i - 2]) % 7;
        if(f[i] == bi2 && f[i - 1] == bi1){
            js = i; break;
        }
    }
    for(int i = 1; i <= js - 3; i ++)
        f[i] = f[i + 2];
    js -= 4; 
    n -= 2;
    LL ans = n % js;
    if(!ans) printf("%lld", f[js] % 7);
    else printf("%lld", f[ans] % 7);
    return 0;
}
/*
455322504
473147848
236471319
*/

T2打表找规律

#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int T;
double n,m;
inline int read()
{
    int x=0,f=1;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    return x*f;
}

int main()
{
    freopen("fseq.in","r",stdin);
    freopen("fseq.out","w",stdout);
    T=read();
    while(T--)
    {
        n=read();m=read();
        if(n<m)    {puts("0.000000");continue;}
        double _1=n-m+1,_2=n+1;
        printf("%.6lf\n",_1/_2);
    }
    return 0;
}

 

T3

/*
    套路题,没营养
    Tarjan缩点
    求出缩完点后树的直径
    对于每个点,若在最长链上就直接对两个端点取max
    否则就一直往上跳,累加边权,直到跳到最长链上
    然后做上一种情况的操作就好了
*/
#include <cstdio>
#include <iostream>
#define rg register

inline void read (int &n) {
    rg char c = getchar ();
    for (n = 0; !isdigit (c); c = getchar ());
    for (; isdigit (c); n = n * 10 + c - '0', c = getchar ());
}

#define Max 40008

int _v[Max * 20], _n[Max * 20], list[Max * 20], EC = 1, _d[Max * 20];

int N;
inline void In (int u, int v, int d) {
    _v[++ EC] = v, _n[EC] = list[u], list[u] = EC, _d[EC] = d;
}

int t, sk[Max], DC, SC;
int dfn[Max], low[Max], scc[Max];

inline void cmin (int &a, int b) {
    if (b < a) a = b;
}

void Dfs (int n, int l) {
    sk[++ t] = n;
    dfn[n] = low[n] = ++ DC;
    for (rg int i = list[n], v; i; i = _n[i])
        if (i != l && i != (l ^ 1)) {
            if (!dfn[v = _v[i]]) Dfs (v, i), cmin (low[n], low[v]);
            else if (!scc[v]) cmin (low[n], dfn[v]);
        }
    if (low[n] == dfn[n]) {
        ++ SC;
        for (int r = n + 1; t && r != n; -- t)
            r = sk[t], scc[r] = SC;
    }
}

int ev[Max * 20], en[Max * 20], el[Max * 10], ec, ed[Max * 20];

inline void _In (int u, int v, int d) {
    ev[++ ec] = v, en[ec] = el[u], el[u] = ec, ed[ec] = d;
    ev[++ ec] = u, en[ec] = el[v], el[v] = ec, ed[ec] = d;
}

bool Find (int x, int y) {
    for (rg int i = el[x]; i; i = en[i])
        if (ev[i] == y) return true;
    return false;
}

void Tarjan () {
    rg int i;
    for (i = 1; i <= N; ++ i) if (!dfn[i]) Dfs (i, 0);
    for (int n = 1; n <= N; ++ n)
        for (i = list[n]; i; i = _n[i])
            if (scc[n] != scc[_v[i]])
                if (!Find (scc[n], scc[_v[i]])) {
                    _In (scc[n], scc[_v[i]], _d[i]);
                }
}
int Answer[Max];
int dis1[Max], dis2[Max], pos1, pos2, Max1, Max2, pre[Max];
void Gc1 (int n, int F) {
    for (rg int i = el[n], v; i; i = en[i])
        if ((v = ev[i]) != F)
            dis1[v] = dis1[n] + ed[i], Gc1 (v, n);
    if (dis1[n] > Max1) Max1 = dis1[n], pos1 = n;
}
int f[Max];
void Gc2 (int n, int F) {
    f[n] = F;
    for (rg int i = el[n], v; i; i = en[i])
        if ((v = ev[i]) != F) dis2[v] = dis2[n] + ed[i], Gc2 (v, n), pre[v] = n;
    if (dis2[n] > Max2) Max2 = dis2[n], pos2 = n;
}
bool isc[Max];
inline int max (int a, int b) {
    return a > b ? a : b;
}
void GetAnswer () {
    Gc1 (1, 0), Gc2 (pos1, 0);
    rg int i;
    for (i = pos2; i; i = pre[i])
        isc[i] = true;
    rg int n;
    int res = 0, j;
    for (i = 1; i <= SC; ++ i) {
        res = 0;
        for (n = i; !isc[n] && n; n = f[n]) {
            for (j = el[n]; j; j = en[j])
                if (ev[j] == f[n]) {
                    res += ed[j];
                    break;
                }
        }
        res += max (dis2[n], Max2 - dis2[n]);
        Answer[i] = res;
    }
    for (i = 1; i <= N; ++ i)
        printf ("%d\n", Answer[scc[i]]);
}
int main (int argc, char *argv[]) {
    int x, y, M, z;
    read (N), read (M);
    for (rg int i = 1; i <= M; ++ i)
        read (x), read (y), read (z), In (x, y, z), In (y, x, z);

    Tarjan ();

    GetAnswer ();

    return 0;
}

 

更好理解的思路:

首先缩点

然后找出树的直径

对于在树上的点,输出该点到直径两端点的较大值

否则输出该点到直径的距离+该点所在链与直径的交点处到直径两个端点的较大值

 

posted @ 2017-11-07 21:41  ioioioioioio  阅读(262)  评论(0编辑  收藏  举报