随笔- 23  文章- 0  评论- 0 

---恢复内容开始---

红小豆少见的及时更新系列

 

I  three points 1

  当大家在枚举少量情况并检验试图找到一个答案的时候,我总是在所有情况里试图构造一个正确的答案

  于是大家AK了我也没AC,完。

  一个三角形在矩形里放置,并考虑点和边的顺序,有效的情况一共就六种,就算加上“广义三角形”-----直线也是ok的。当固定一个点在原点时,另一个在矩形的边上的点有两种情况,如下图,根据这两点的坐标和此时可知的夹角可以得到第三点的坐标,对其进行边界检查,符合即可输出。因为默认把矩形最长边放在下方,所以根据是否有旋转矩形,还要把点的坐标旋转回去。

  考虑到精度问题没有用acos什么的,所以还要根据情况特判某个角的cos,(场上就各种-nan来着)_(:з」∠)_

  场上写的未AC码已经不想看了,重写了一份补题码自我感觉良好

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
typedef long long LL;
#define CR(t,x) const t&x
#define CRP(x) CR(point,x)
#define double long double
const double eps = 1e-12;
double w, h, a[5];
int t;
struct point
{
    double x, y;
    void chg() { swap(x, y); }
}p[5];
double dis(CR(point, l), CR(point, r)) {
    return (l.y - r.y) * (l.y - r.y) + (l.x - r.x) * (l.x - r.x);
}

int che(int d, int l, int r, int x, int y, int z,bool c)
{
    p[y].y = (a[d] > w) ? (sqrt(a[d] * a[d] - w * w)) : 0;
    p[y].x = p[y].y ? w : a[d];
    double cB = (a[d] * a[d] + a[l] * a[l] - a[r] * a[r]) / (2 * a[d] * a[l]);
    double sB = sqrt(1 - cB * cB);
    double cP = p[y].y ? ((a[d] * a[d] + w * w - p[y].y * p[y].y) / (2 * a[d] * w)) : 1;
    double sP = sqrt(1 - cP * cP);
    double cQ = cB * cP - sB * sP;
    double sQ = sqrt(1 - cQ * cQ);
    p[x].x = p[x].y = 0;
    p[z].x = a[l] * cQ; p[z].y = a[l] * sQ;
    if (p[z].x + eps >= 0 && p[z].x - eps <= w && p[z].y + eps >= 0 && p[z].y - eps <= h ) {
        if (c) { p[x].chg(); p[y].chg(); p[z].chg(); }
        printf("%.12Lf %.12Lf %.12Lf %.12Lf %.12Lf %.12Lf\n", p[1].x, p[1].y, p[2].x, p[2].y, p[3].x, p[3].y);
        return 1;
    }
    return 0;
}


int main()
{
    scanf("%d", &t);
    while (t--) {
        double ma; bool fg = 0;
        scanf("%Lf%Lf%Lf%Lf%Lf", &w, &h, &a[1], &a[2], &a[3]);
        ma = max(a[1], max(a[2], a[3]));
        if (h > w)swap(w, h), fg = 1;
        if (che(1, 2, 3, 1, 2, 3,fg));
        else if (che(1, 3, 2, 2, 1, 3,fg));
        else if (che(2, 1, 3, 1, 3, 2,fg));
        else if (che(2, 3, 1, 3, 1, 2,fg));
        else if (che(3, 2, 1, 3, 2, 1,fg));
        else che(3, 1, 2, 2, 3, 1,fg);

    }
    return 0;
}
three points 1

 

 

---恢复内容结束---

有上面这个东西是因为吃了个饭电脑好像自己重启了_(:з」∠)_

 

G  subsequence 1

  应该和020互换题目做的)

  这是一道基础dp,出题人如是说。用到了组合数学,补充。

  第一维表示s串位置,第二维表示t串位置,存当前方案数:

    首先当前方案数以i-1位与j位匹配的方案数为基础;

    如果这一位上s比t大,那么  后面n-i位里随便选m-j个的方案数(选了这位之后,后面就可以随便选)  乘上  两个串匹配到上一位的时候的方案数(组合嘛)  就是选择加入这一位提供的答案贡献(直接加进ans里);

    如果这一位s和t相等,那么该位的方案数就再加上[i-1][j-1]的时候的方案数,即选ta或者不选ta

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
typedef long long LL;
const LL mod = 998244353;
int t, n, m;
char s1[3005], s2[3005];
LL ans;
LL c[3005][3005],d[3005][3005];

void C()
{
    c[0][0] = 1;
    for(int i=1;i<=3000;i++){
        c[i][0] = 1;
        for (int j = 1; j <= 3000; j++)
            c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % mod;
    }
}

int main()
{
    scanf("%d", &t);
    C();
    while (t--) {
        scanf("%d%d", &n, &m);
        scanf("%s %s", s1+1, s2+1);
        ans = 0;
        for (int i = 1; i <= n; i++){
            if (s1[i] == '0')continue;
            for (int j = m; j <= n - i; j++)
                ans = (ans + c[n-i][j]) % mod;
        }
        for (int i = 0; i <= n; i++)d[i][0] = 1;
        for(int i=1;i<=n;i++)
            for (int j = 1; j <=min(m,i); j++) {
                d[i][j] = d[i-1][j];
                if (s1[i] > s2[j])ans = (ans + d[i-1][j-1] * c[n - i][m - j] % mod) % mod;
                if (s1[i] == s2[j])d[i][j] = (d[i][j] + d[i - 1][j - 1]) % mod;
            }
        cout << ans << endl;
    }

    return 0;
}
subsequence 1

  其实[0][0]应该是0的,因为两个空集不会larger than。但是如果第一位就大于的话,就要用到[0][0]来乘组合数,如果ta等于0就会失去一部分方案┓( ´∀` )┏

 

  以上!

 posted on 2019-08-02 21:06 Nonad 阅读(...) 评论(...) 编辑 收藏