Problem K:Kindergarten Physics
链接:http://acm.hdu.edu.cn/showproblem.php?pid=6812
这题算是比较坑了,刚开始想着还要用公式推一推,本身物理就不好,只好放掉了。赛后才发现这题只要原样输出即可,因为要求的误差完全可以满足😂;

#include<iostream>
using namespace std;
int main(){
    int T,a,b,d,t;
    scanf("%d",&T);
    while(T --) {
        scanf("%d%d%d%d",&a,&b,&d,&t);
        printf("%d\n",d);
    } 
    return 0;
}

Problem D:Deliver the Cake
链接:http://acm.hdu.edu.cn/showproblem.php?pid=6805
这题还是看得比较明白的,当时也尝试过了,可惜还是t了。最近刚学完基础的图论,遇到这种很直白的图论题还是想试试身手的。一开始写了个dijstra,心思比较单纯,直接t了。后面想改优先级队列,不过不太会写,找了一些板子,本来都快出来了,才发现自己关于左右手这一块漏想了一种情况。题解看不太懂,网上找了一篇比较明白的,把每个点一分为二,用以表示左右手两种情况或者说是状态。反正最后就是优先级队列+dijstra,这一块还不熟,一知半解。暂时先放着,最近在学算法竞赛进阶指南,日后再看到图论部分再回来解决。

#include<iostream>
#include<queue>
#include<vector>
typedef long long LL;
using namespace std;
const int MAXN = 200005;
struct Edge { int v, w; };
struct Node {
    LL d; int u, t;
    bool operator<(const Node &n) const { return d > n.d; }
};
vector<Edge> edge[MAXN];
LL dis[MAXN][2];
int T, n, m, s, t, x;
char str[MAXN];
priority_queue<Node> pq;
int main() {
    for (scanf("%d", &T); T--;) {
        scanf("%d%d%d%d%d", &n, &m, &s, &t, &x);
        scanf("%s", str + 1);
        for (int i = 1; i <= m; i++) {
            int u, v, w; scanf("%d%d%d", &u, &v, &w);
            edge[u].push_back(Edge { v, w });
            edge[v].push_back(Edge { u, w });
        }
        for (int i = 1; i <= n; i++) dis[i][0] = dis[i][1] = 1e18;
        if (str[s] != 'R') pq.push(Node { dis[s][0] = 0, s, 0 });
        if (str[s] != 'L') pq.push(Node { dis[s][1] = 0, s, 1 });
        while (!pq.empty()) {
            Node d = pq.top(); pq.pop();
            if (dis[d.u][d.t] < d.d) continue;
            if (d.u == t) break;
            for (const Edge &e : edge[d.u]) {
                LL w = e.w + d.d;
                int t = str[e.v] == 'R' ? 1 : (str[e.v] == 'L' ? 0 : d.t);
                if (t == d.t && w < dis[e.v][t])
                    pq.push(Node { dis[e.v][t] = w, e.v, t });
                w += x;
                if (str[e.v] == 'M') t = !t;
                if (t != d.t && w < dis[e.v][t])
                    pq.push(Node { dis[e.v][t] = w, e.v, t });
            }
        }
        printf("%lld\n", min(dis[t][0], dis[t][1]));
        while (!pq.empty()) pq.pop();
        for (int i = 1; i <= n; i++) edge[i].clear();
    }
    return 0;
}

Problem E:Equal Sentences
链接:http://acm.hdu.edu.cn/showproblem.php?pid=6806
这道题目本身并不难,可惜当时我看不懂题意,读题能力还是太差了😶。如果仔细观察,不难发现如果一个序列相邻元素两两不同,那么方案数就是斐波那契数列,至于答案就是这些可以划分出的斐波那契数列的乘积了。

#include<iostream>
typedef long long LL;
using namespace std;
const int MAXN = 200005, MOD = 1e9 + 7;
LL f[MAXN];
int T, n;
string aa[MAXN];
char str[MAXN];
int main(){
    f[0]=1,f[1]=1;
    for(int i=2;i<=1e5;i++)
        f[i]=(f[i-1]+f[i-2])%MOD;
    for(scanf("%d",&T);T--;){
        scanf("%d",&n);
        int cnt=0;
        LL ans=1;
        for(int i=1;i<=n;i++){
            scanf("%s",str);
            aa[i]=str;
            if(aa[i]!=aa[i-1])++cnt;
            else ans =ans*f[cnt]% MOD,cnt=1;
        }
        ans = ans * f[cnt] % MOD;
        printf("%lld\n", ans);
    }
    return 0;
}