牛客小白月赛16

A.只有1个的时候后手胜,其他先手胜

没证明,手推了前几个先手胜的看榜上过穿了就交了

#include <map>
#include <set>
#include <ctime>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
#define For(i, x, y) for(int i=x;i<=y;i++) 
#define _For(i, x, y) for(int i=x;i>=y;i--)
#define Mem(f, x) memset(f,x,sizeof(f)) 
#define Sca(x) scanf("%d", &x)
#define Sca2(x,y) scanf("%d%d",&x,&y)
#define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define Scl(x) scanf("%lld",&x); 
#define Pri(x) printf("%d\n", x)
#define Prl(x) printf("%lld\n",x); 
#define CLR(u) for(int i=0;i<=N;i++)u[i].clear();
#define LL long long
#define ULL unsigned long long 
#define mp make_pair
#define PII pair<int,int>
#define PIL pair<int,long long>
#define PLL pair<long long,long long>
#define pb push_back
#define fi first
#define se second
typedef vector<int> VI;
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;}
const double eps = 1e-9;
const int maxn = 110;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
int N,M,K;
int main(){
    Sca(N);
    if(N == 1) puts("Yang");
    else puts("Shi");
    return 0;
}
A

 

B.按照题意暴力递推出来,求个每一层的前缀和

pre[r] - pre[l - 1]直接计算

#include <map>
#include <set>
#include <ctime>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
#define For(i, x, y) for(int i=x;i<=y;i++) 
#define _For(i, x, y) for(int i=x;i>=y;i--)
#define Mem(f, x) memset(f,x,sizeof(f)) 
#define Sca(x) scanf("%d", &x)
#define Sca2(x,y) scanf("%d%d",&x,&y)
#define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define Scl(x) scanf("%lld",&x); 
#define Pri(x) printf("%d\n", x)
#define Prl(x) printf("%lld\n",x); 
#define CLR(u) for(int i=0;i<=N;i++)u[i].clear();
#define LL long long
#define ULL unsigned long long 
#define mp make_pair
#define PII pair<int,int>
#define PIL pair<int,long long>
#define PLL pair<long long,long long>
#define pb push_back
#define fi first
#define se second
typedef vector<int> VI;
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;}
const double eps = 1e-9;
const int maxn = 1010;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
int N,M,K;
LL MAP[maxn][maxn];
LL pre[maxn];
int main(){
    Sca2(N,M);
    pre[1] = 1;
    for(int i = 2; i <= N ; i ++){
        MAP[i][1] = MAP[i][i] = i;
        pre[i] = (2 * i + pre[i - 1]) % mod;
        for(int j = 2; j < i ; j ++){
            MAP[i][j] = (MAP[i - 1][j] + MAP[i - 1][j - 1]) % mod;
            pre[i] += MAP[i][j]; pre[i] %= mod;
        }
    }
    while(M--){
        int l,r; Sca2(l,r);
        Prl((pre[r] - pre[l - 1] + mod) % mod);
    }
    return 0;
}
B

 

C.题目写的花里胡哨仿佛要上数据结构

看了一眼范围暴力可过

#include <map>
#include <set>
#include <ctime>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
#define For(i, x, y) for(int i=x;i<=y;i++) 
#define _For(i, x, y) for(int i=x;i>=y;i--)
#define Mem(f, x) memset(f,x,sizeof(f)) 
#define Sca(x) scanf("%d", &x)
#define Sca2(x,y) scanf("%d%d",&x,&y)
#define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define Scl(x) scanf("%lld",&x); 
#define Pri(x) printf("%d\n", x)
#define Prl(x) printf("%lld\n",x); 
#define CLR(u) for(int i=0;i<=N;i++)u[i].clear();
#define LL long long
#define ULL unsigned long long 
#define mp make_pair
#define PII pair<int,int>
#define PIL pair<int,long long>
#define PLL pair<long long,long long>
#define pb push_back
#define fi first
#define se second
typedef vector<int> VI;
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;}
const double eps = 1e-9;
const int maxn = 1010;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
int N,M,K;
int a[maxn];
int main(){
    Sca2(N,M);
    for(int i = 1; i <= N ; i ++) Sca(a[i]);
    while(M--){
        int x; Sca(x);
        int ans = 0;
        int cnt = 0;
        for(int i = 1; i <= N ; i ++){
            if(x >= a[i]){
                cnt = 0;
                continue;
            }
            if(!cnt){
                cnt = 1; ans++;
            }
        }
        Pri(ans);
    }
    return 0;
}
C

 

D.感觉尺取可以做。

但我还是离散了一下前缀和,树状数组维护比当前前缀和小的最小的位置。nlogn直接做

#include <map>
#include <set>
#include <ctime>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
#define For(i, x, y) for(int i=x;i<=y;i++) 
#define _For(i, x, y) for(int i=x;i>=y;i--)
#define Mem(f, x) memset(f,x,sizeof(f)) 
#define Sca(x) scanf("%d", &x)
#define Sca2(x,y) scanf("%d%d",&x,&y)
#define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define Scl(x) scanf("%lld",&x); 
#define Pri(x) printf("%d\n", x)
#define Prl(x) printf("%lld\n",x); 
#define CLR(u) for(int i=0;i<=N;i++)u[i].clear();
#define LL long long
#define ULL unsigned long long 
#define mp make_pair
#define PII pair<int,int>
#define PIL pair<int,long long>
#define PLL pair<long long,long long>
#define pb push_back
#define fi first
#define se second
typedef vector<int> VI;
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;}
const double eps = 1e-9;
const int maxn = 2e6 + 1110;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
int N,M,K;
int a[maxn],pre[maxn];
int Hash[maxn];
int tree[maxn];
void add(int u,int v){
    for(;u <= N; u += u & -u) tree[u] = min(tree[u],v);
}
int getmin(int u){
    int ans = INF;
    for(;u > 0; u -= u & -u) ans = min(ans,tree[u]);
    return ans;
}
int main(){
    Sca(N);
    int cnt = 0;
    for(int i = 0 ;i <= N + 1; i ++) tree[i] = INF;
    for(int i = 1; i <= N ; i ++){
        Sca(a[i]); pre[i] = pre[i - 1] + a[i];
        Hash[++cnt] = pre[i];
    }
    Hash[++cnt] = 0;
    sort(Hash + 1,Hash + 1 + cnt);
    cnt = unique(Hash + 1,Hash + 1 + cnt) - Hash - 1;
    int x = lower_bound(Hash + 1,Hash + 1 + cnt,0) - Hash;
    add(x,0);
    int ans = 0;
    for(int i = 1; i <= N; i ++){
        pre[i] = lower_bound(Hash + 1,Hash + 1 + cnt,pre[i]) - Hash;
        add(pre[i],i);
        ans = max(ans,i - getmin(pre[i] - 1));
    }
    Pri(ans);
    return 0;
}
D

 

E.这个数据范围的意思就是告诉你直接BFS递推就可以了

#include <map>
#include <set>
#include <ctime>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
#define For(i, x, y) for(int i=x;i<=y;i++) 
#define _For(i, x, y) for(int i=x;i>=y;i--)
#define Mem(f, x) memset(f,x,sizeof(f)) 
#define Sca(x) scanf("%d", &x)
#define Sca2(x,y) scanf("%d%d",&x,&y)
#define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define Scl(x) scanf("%lld",&x); 
#define Pri(x) printf("%d\n", x)
#define Prl(x) printf("%lld\n",x); 
#define CLR(u) for(int i=0;i<=N;i++)u[i].clear();
#define LL long long
#define ULL unsigned long long 
#define mp make_pair
#define PII pair<int,int>
#define PIL pair<int,long long>
#define PLL pair<long long,long long>
#define pb push_back
#define fi first
#define se second
typedef vector<int> VI;
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;}
const double eps = 1e-9;
const int maxn = 10010;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
int N,M,K;
bool vis[10][10][maxn];
int MAP[10][10];
struct node{
    int x,y,sum;
    node(){}
    node(int x,int y,int sum):x(x),y(y),sum(sum){}
};
const int a[2][2] = {0,1,1,0};
bool check(int x,int y){
    return 1 <= x && x <= N && 1 <= y &&y <= N;
}
int main(){
    Sca(N);
    for(int i = 1; i <= N ; i ++){
        for(int j = 1; j <= N; j ++){
            Sca(MAP[i][j]);
        }
    }
    queue<node>Q; Q.push(node(1,1,MAP[1][1]));
    vis[1][1][MAP[1][1]] = 1;
    while(!Q.empty()){
        node u = Q.front(); Q.pop();
        for(int i = 0 ; i < 2; i ++){
            node h = u;
            h.x += a[i][0]; h.y += a[i][1];
            if(!check(h.x,h.y)) continue;
            h.sum += MAP[h.x][h.y];
            if(!vis[h.x][h.y][h.sum]){
                vis[h.x][h.y][h.sum] = 1;
                Q.push(h);
            }
        }
    }
    int ans = 0;
    for(int i = 0 ; i < maxn; i ++){
        if(vis[N][N][i]) ans++;
    }
    Pri(ans);
    return 0;
}
E

 

F.题目里说每个大兄弟的两个属性两两之间互不相同,这很重要

按照第一关键字从大到小排序,那么每一趟就相当于在所有大兄弟里找一个第二关键字递增的序列

暴力n ^ 2肯定不行,想办法优化就可以了,我这边先预处理nxt[i]表示下一个比这个位置的第二关键字高的位置,然后查询的时候i直接跳nxt[i]

然后并查集维护所有已经被选择过的大兄弟就可以了

#include <map>
#include <set>
#include <ctime>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
#define For(i, x, y) for(int i=x;i<=y;i++) 
#define _For(i, x, y) for(int i=x;i>=y;i--)
#define Mem(f, x) memset(f,x,sizeof(f)) 
#define Sca(x) scanf("%d", &x)
#define Sca2(x,y) scanf("%d%d",&x,&y)
#define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define Scl(x) scanf("%lld",&x) 
#define Pri(x) printf("%d\n", x)
#define Prl(x) printf("%lld\n",x) 
#define CLR(u) for(int i=0;i<=N;i++)u[i].clear();
#define LL long long
#define ULL unsigned long long 
#define mp make_pair
#define PII pair<int,int>
#define PIL pair<int,long long>
#define PLL pair<long long,long long>
#define pb push_back
#define fi first
#define se second
typedef vector<int> VI;
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;}
const double eps = 1e-9;
const int maxn = 1e5 + 10;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
int N,M,K;
struct node{
    int fi,se,id;
}girl[maxn];
int fa[maxn];
void init(){
    for(int i = 1; i <= N + 1; i ++) fa[i] = i;
}
int find(int x){
    return x == fa[x]?x:fa[x] = find(fa[x]);
}
void Union(int a,int b){
    a = find(a); b = find(b);
    fa[a] = b;
}
int nxt[maxn];
int ans[maxn];
bool cmp(node a,node b){
    return a.fi > b.fi;
}
int main(){
    Sca(N); init();
    for(int i = 1; i <= N ; i ++){
        Sca2(girl[i].fi,girl[i].se);
        girl[i].id = i;
    }
    sort(girl + 1,girl + 1 + N,cmp);
    girl[N + 1].se = INF;
    for(int i = N; i >= 1; i --){
        int to = i + 1;
        while(girl[i].se > girl[to].se){
            to = nxt[to];
        }
        nxt[i] = to;
    }
    int tot = 0;
    while(1){
        tot++;
        int s = find(1);
        if(s == N + 1) break;
        int high = girl[s].se;
        while(s != N + 1){
            Union(s,s + 1);
            ans[girl[s].id] = tot;
            high = girl[s].se;
            while(s != N + 1 && girl[s].se <= high) s = find(nxt[s]);
        }
    }  
    for(int i = 1; i <= N ; i ++) Pri(ans[i]);
    return 0;
}
F

 

G.小学数学

#include <map>
#include <set>
#include <ctime>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
#define For(i, x, y) for(int i=x;i<=y;i++) 
#define _For(i, x, y) for(int i=x;i>=y;i--)
#define Mem(f, x) memset(f,x,sizeof(f)) 
#define Sca(x) scanf("%d", &x)
#define Sca2(x,y) scanf("%d%d",&x,&y)
#define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define Scl(x) scanf("%lld",&x); 
#define Pri(x) printf("%d\n", x)
#define Prl(x) printf("%lld\n",x); 
#define CLR(u) for(int i=0;i<=N;i++)u[i].clear();
#define LL long long
#define ULL unsigned long long 
#define mp make_pair
#define PII pair<int,int>
#define PIL pair<int,long long>
#define PLL pair<long long,long long>
#define pb push_back
#define fi first
#define se second
typedef vector<int> VI;
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;}
const double eps = 1e-9;
const int maxn = 110;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
int N,M,K;
double PI = acos(-1.0);
int main(){
    double N;
    cin >> N;
    printf("%.3lf",N * N / (2 * PI));
    return 0;
}
G

 

H. 

gcd(a1,a2,a3,a4 .. ,an) = gcd(a1,a2 - a1,a3 - a2,a4 - a3,....an - an - 1)

通过上面这个式子,可以把区间维护gcd变成区间维护差分序列的gcd,乍一看还是区间gcd,但是差分序列的维护就直接从区间修改降到了单点修改。

凑巧的是区间差的最大值也可以直接维护一个差分序列的最大值,再用树状数组维护一下原序列(因为上面式子右边还有一个a1,这不是差分) 

这道题就解决了

#include <map>
#include <set>
#include <ctime>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
#define For(i, x, y) for(int i=x;i<=y;i++) 
#define _For(i, x, y) for(int i=x;i>=y;i--)
#define Mem(f, x) memset(f,x,sizeof(f)) 
#define Sca(x) scanf("%d", &x)
#define Sca2(x,y) scanf("%d%d",&x,&y)
#define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define Scl(x) scanf("%lld",&x) 
#define Pri(x) printf("%d\n", x)
#define Prl(x) printf("%lld\n",x) 
#define CLR(u) for(int i=0;i<=N;i++)u[i].clear();
#define LL long long
#define ULL unsigned long long 
#define mp make_pair
#define PII pair<int,int>
#define PIL pair<int,long long>
#define PLL pair<long long,long long>
#define pb push_back
#define fi first
#define se second
typedef vector<int> VI;
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;}
const double eps = 1e-9;
const int maxn = 3e5 + 10;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
int N,M,K;
LL gcd(LL a,LL b){
    return b == 0?a:gcd(b,a % b);
}
LL a[maxn];
struct Tree{
    int l,r;
    LL Gcd,Max,real;
}tree[maxn << 2];
void Pushup(int t){
    tree[t].Gcd = gcd(tree[t << 1].Gcd,tree[t << 1 | 1].Gcd);
    tree[t].Max = max(tree[t << 1].Max,tree[t << 1 | 1].Max);
}
void Build(int t,int l,int r){
    tree[t].l = l; tree[t].r = r;
    if(l == r){
        tree[t].real = a[r] - a[r - 1];
        tree[t].Gcd = tree[t].Max = abs(tree[t].real);
        return;
    }
    int m = l + r >> 1;
    Build(t << 1,l,m); Build(t << 1 | 1,m + 1,r);
    Pushup(t);
}
void update(int t,int p,LL v){
    if(tree[t].l == tree[t].r){
        tree[t].real += v;
        tree[t].Gcd = tree[t].Max = abs(tree[t].real);
        return;
    }
    int m = tree[t].l + tree[t].r >> 1;
    if(p <= m) update(t << 1,p,v);
    else update(t << 1 | 1,p,v);
    Pushup(t);
}
LL queryMax(int t,int l,int r){
    if(l <= tree[t].l && tree[t].r <= r){
        return tree[t].Max;
    }
    int m = tree[t].l + tree[t].r >> 1;
    if(r <= m) return queryMax(t << 1,l,r);
    else if(l > m) return queryMax(t << 1 | 1,l,r);
    else{
        return max(queryMax(t << 1,l,m),queryMax(t << 1 | 1,m + 1,r));
    }
}
LL queryGcd(int t,int l,int r){
    if(l <= tree[t].l && tree[t].r <= r){
        return tree[t].Gcd;
    }
    int m = tree[t].l + tree[t].r >> 1;
    if(r <= m) return queryGcd(t << 1,l,r);
    else if(l > m) return queryGcd(t << 1 | 1,l,r);
    else{
        return gcd(queryGcd(t << 1,l,m),queryGcd(t << 1 | 1,m + 1,r));
    }
}
LL BIT[maxn];
void add(int x,LL v){
    for(;x <= N + 10;x += x & -x) BIT[x] += v;
}
LL getsum(int x){
    LL ans = 0;
    for(;x > 0;x -= x & -x) ans += BIT[x];
    return ans;
}
int main(){
    Sca2(N,M);
    for(int i = 1; i <= N ; i ++){
         Scl(a[i]);
         add(i,a[i]); add(i + 1,-a[i]);
    }
    Build(1,2,N);
    while(M--){
        int op,l,r; Sca3(op,l,r);
        if(op == 1){
            LL x; Scl(x);
            if(l != 1) update(1,l,x);
            if(r != N) update(1,r + 1,-x);
            add(l,x); add(r + 1,-x);
        }else if(op == 2){
            if(l == r) puts("0");
            else Prl(queryMax(1,l + 1,r));
        }else{
            LL x = getsum(l);
            if(l == r) Prl(x);
            else Prl(gcd(x,queryGcd(1,l + 1,r)));
        }
    }
    return 0;
}
H

 

I.数论一生黑,不会

补: 第一步前进的期望dp[1]是1 / a,(因为不会后退)

后面每一步前进的期望dp[i] = 1 (摇到前进) + b / a (摇到平局) + c / a * (dp[i - 1] + 1) (摇到后退,代价是摇了一下后退并且需要再上来)

#include <map>
#include <set>
#include <ctime>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
#define For(i, x, y) for(int i=x;i<=y;i++)  
#define _For(i, x, y) for(int i=x;i>=y;i--)
#define Mem(f, x) memset(f,x,sizeof(f))  
#define Sca(x) scanf("%d", &x)
#define Sca2(x,y) scanf("%d%d",&x,&y)
#define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define Scl(x) scanf("%lld",&x)  
#define Pri(x) printf("%d\n", x)
#define Prl(x) printf("%lld\n",x)  
#define CLR(u) for(int i=0;i<=N;i++)u[i].clear();
#define LL long long
#define ULL unsigned long long  
#define mp make_pair
#define PII pair<int,int>
#define PIL pair<int,long long>
#define PLL pair<long long,long long>
#define pb push_back
#define fi first
#define se second 
typedef vector<int> VI;
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;}
const double eps = 1e-9;
const int maxn = 110;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7; 
LL dp[maxn];
LL quick_power(LL a,LL b){
    LL ans = 1;
    while(b){
        if(b & 1) ans = ans * a % mod;
        b >>= 1;
        a = a * a % mod;
    }
    return ans;
}
LL inv(LL x){
    return quick_power(x,mod - 2);
}
int main(){
    LL n,a,b;
    cin >> n >> a >> b;
    LL ans = dp[1] = inv(a);
    LL c = ((1 - a - b) % mod + mod) % mod;
    for(int i = 2; i < n; i ++){
        dp[i] = 1 + c * inv(a) % mod * (1 + dp[i - 1]) % mod + b * inv(a) % mod;
        dp[i] %= mod;
        ans = (ans + dp[i]) % mod; 
    }
    Prl(ans);
    return 0;
}
I

 

 

J.似乎只是个略微麻烦点的裸最短路罢了,dis[i][j]表示第i条线路第j个站点的最少花费,Dijkstra直接上就好了

#include <map>
#include <set>
#include <ctime>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
#define For(i, x, y) for(int i=x;i<=y;i++) 
#define _For(i, x, y) for(int i=x;i>=y;i--)
#define Mem(f, x) memset(f,x,sizeof(f)) 
#define Sca(x) scanf("%d", &x)
#define Sca2(x,y) scanf("%d%d",&x,&y)
#define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define Scl(x) scanf("%lld",&x) 
#define Pri(x) printf("%d\n", x)
#define Prl(x) printf("%lld\n",x) 
#define CLR(u) for(int i=0;i<=N;i++)u[i].clear();
#define LL long long
#define ULL unsigned long long 
#define mp make_pair
#define PII pair<int,int>
#define PIL pair<int,long long>
#define PLL pair<long long,long long>
#define pb push_back
#define fi first
#define se second
typedef vector<int> VI;
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;}
const double eps = 1e-9;
const int maxn = 1010;
const int maxm = 510;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
int N,M,s,t;
int a[maxm],b[maxm];
int nxt[maxm][maxn],pre[maxm][maxn];
int tmp[maxn];
vector<int>P[maxn];
LL dis[maxm][maxn];
struct node{
    int n,m;
    LL val;
    node(){}
    node(int n,int m,LL val):n(n),m(m),val(val){}
    friend bool operator < (node a,node b){
        return a.val > b.val;
    }
};
void Dijkstra(){
    for(int i = 0 ; i <= M; i ++){
        for(int j = 0 ; j <= N ; j ++) dis[i][j] = 1e18;
    }
    dis[0][s] = 0;
    priority_queue<node>Q; Q.push(node(s,0,0));
    while(!Q.empty()){
        node u = Q.top(); Q.pop();
        if(dis[u.m][u.n] < u.val) continue;
        if(pre[u.m][u.n]){
            node h = u; h.n = pre[u.m][u.n]; h.val += b[u.m];
            if(dis[h.m][h.n] > h.val){
                dis[h.m][h.n] = h.val; Q.push(h);
            }
        }
        if(nxt[u.m][u.n]){
            node h = u; h.n = nxt[u.m][u.n]; h.val += b[u.m];
            if(dis[h.m][h.n] > h.val){
                dis[h.m][h.n] = h.val; Q.push(h);
            }
        }
        if(u.m){
            node h = u; h.m = 0;
            if(dis[h.m][h.n] > h.val){
                dis[h.m][h.n] = h.val; Q.push(h);
            }
        }
        if(!u.m){
            for(int i = 0 ; i < P[u.n].size(); i ++){
                int to = P[u.n][i];
                node h = u; h.m = to; h.val += a[to];
                if(dis[h.m][h.n] > h.val){
                    dis[h.m][h.n] = h.val; Q.push(h);
                }
            }
        }
    }
}
int main(){
    scanf("%d%d%d%d",&N,&M,&s,&t);
    for(int i = 1; i <= M ; i ++){
        int k;
        scanf("%d%d%d",&a[i],&b[i],&k);
        for(int j = 1; j <= k ; j ++){
            Sca(tmp[j]); P[tmp[j]].push_back(i);
            nxt[i][tmp[j - 1]] = tmp[j];
            pre[i][tmp[j]] = tmp[j - 1];
        }
    }
    Dijkstra();
    LL ans = 1e18;
    for(int i = 0 ; i <= M ; i ++){
        ans = min(ans,dis[i][t]);
    }
    if(ans == 1e18) ans = -1;
    Prl(ans);
    return 0;
}
J

 

posted @ 2019-07-12 22:19  Hugh_Locke  阅读(428)  评论(0编辑  收藏  举报