机房测试 8.11

8.11 机房测试


a

问题描述

罗马字母 I,V,X,L I , V , X , L 分别对应着1,5,10,50。其他的字母不允许使用。一个长为 n n 由罗马字母组成的字符串,我们不计顺序地计算它所对应的数值。如 XXXV X X X V 代表35, IXI I X I 代表12。注意 IX I X 代表11 而不是9。对于长度 n n 的由上述罗马字母组成的字符串最多能代表多少种数值。

数据范围

对于20%的数据, n15 n ⩽ 15 ,
对于 60% 60 % 的数据, n60 n ⩽ 60 ,
对于 100% 100 % 的数据, n1e9 n ⩽ 1 e 9

思路

题解推荐

注意!
该题解中四种权值变成 {0,4,9,49} { 0 , 4 , 9 , 49 } 可以理解为, 长度为n 的字符串, 每个位置都预先放1 在上面。对于同一个数值来说,4 和9 占的比例越小越优,所以 {4} { 4 } 不会超过8 个, {9} { 9 } 不会超过48 个。

其实就是一道17个for循环打表乱搞轻松AC的水水签到题(一个地方没开long long 少了40分的我失去梦想)

打表程序

#include<bits/stdc++.h>
#define f(i,j,k) for(int i=1;i<=4;i++) for(int j=1;j<=4;j++) for(int k=1;k<=4;k++)
int a[5]={0,1,5,10,50};
bool fl[50000+5];
int main() {
    f(q,w,e)f(r,t,y)f(u,i,o)f(p,aa,s)f(d,f,g)f(h,j,k) {
        int sum=a[q]+a[w]+a[e]+a[r]+a[t]+a[y]+a[u]+a[i]+a[o]+a[p]+a[aa]+a[s]+a[d]+a[f]+a[g]+a[h]+a[j]+a[k];
        fl[sum]=true;
    }
    int ans=0;
    for(int i=1;i<=5000;i++) if(fl[i]) ans++;
    printf("%d\n",ans);
}

跑出=18需要10min左右

标程

#include<cstdio>
#include<iostream>
#define FN "a"

int ans[20]={0,4,10,20,35,56,83,116,155,198,244,292,341,390,439,488};

int main() {
    freopen(FN".in","r",stdin);
    freopen(FN".out","w",stdout);
    int n;
    scanf("%d",&n);
    if(n<=15) printf("%d\n",ans[n]);
    else {
        long long ANS=1LL*(n-15)*49+488;
        printf("%I64d\n",ANS);
    }
}

b

问题描述

输入 x,y x , y
比较 xy x y yx y x 大小

数据范围

对于 20% 20 % 的数据, x,y50 x , y ⩽ 50
对于 100% 100 % 的数据, 1T50 1 ⩽ T ⩽ 50 1x,y1e9 1 ⩽ x , y ⩽ 1 e 9

思路

想了很久啷个找规律,结果取个对数一算就TM出来了

天要绝我啊!

有个同学非要写 log2() l o g 2 ( ) 函数,结果被搞成0分?

比较 xy x y yx y x 大小相当于比较 ylg(x) y ∗ l g ( x ) xlg(y) x ∗ l g ( y ) 的大小

简单明了的想法

但机房有个同学直接比较 x,y x , y 大小+特判竟然就A了?

标程

#include<cstdio>
#include<iostream>
#include<cmath>
#define FN "b"

int main() {
    freopen(FN".in","r",stdin);
    freopen(FN".out","w",stdout);
    int T;
    scanf("%d",&T);
    while(T--) {
        int x,y;
        scanf("%d%d",&x,&y);
        char c;
        if(x==y) c='=';
        else if(y*log(x)==x*log(y)) c='=';
        else if(y*log(x)>x*log(y)) c='>';
        else c='<';
        printf("%c\n",c);
    }
    return 0;
}

c

问题描述

两个数a 和b (a < b) 被称为质数相关,是指a×p = b,这里p 是一个质数。一个集合S被称为质数相关,是指S 中存在两个质数相关的数,否则称S 为质数无关。如 {2,8,17} { 2 , 8 , 17 } 质数无关,但 {2,8,16,3,6} { 2 , 8 , 16 , 3 , 6 } 质数相关。现在给定一个集合S,问S 的所有质数无关子集中,最大的子集的大小。

数据范围

集合S 内的数两两不同且范围在1 到500000 之间。
对于 40% 40 % 的数据,, 1n15 1 ⩽ n ⩽ 15
对于 100% 100 % 的数据, 1T20 1 ⩽ T ⩽ 20 1n1000 1 ⩽ n ⩽ 1000

思路

首先要做的就是 n2 n 2 预处理出是否质数相关

法1:二分图

分解质因数,以质因数个数的奇偶性构建二分图。对于两边的数,如果质数相关就建边。
然后你懂得。
二分图最大独立集。

法2:树形DP

解法

标程:二分图

#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
#define maxn 200001
#define mod 10007
#define eps 1e-9
int Num;
char CH[20];
const int inf = 0x3f3f3f3f;

inline ll read() {
    int x = 0, f = 1;
    char ch = getchar();
    while (ch < '0' || ch > '9') {
        if (ch == '-')
            f = -1;
        ch = getchar();
    }
    while (ch >= '0' && ch <= '9') {
        x = x * 10 + ch - '0';
        ch = getchar();
    }
    return x * f;
}
inline void P(int x) {
    Num = 0;
    if (!x) {
        putchar('0');
        puts("");
        return;
    }
    while (x > 0)
        CH[++Num] = x % 10, x /= 10;
    while (Num)
        putchar(CH[Num--] + 48);
    puts("");
}
const int MAXN = 500001;
bool flag[MAXN];
int primes[MAXN], pi;
void GetPrime_1() {
    int i, j;
    pi = 0;
    memset(flag, false, sizeof(flag));
    for (i = 2; i < MAXN; i++)
        if (!flag[i]) {
            primes[i] = 1; 
            for (j = i; j < MAXN; j += i)
                flag[j] = true;
        }
}

vector<int> q[maxn];
int vis[maxn];
int match[maxn];
int a[maxn];
bool cmp(int b, int c) { return b > c; }
int dfs(int x) {
    for (int i = 0; i < q[x].size(); i++) {
        if (vis[q[x][i]] == 0) {
            vis[q[x][i]] = 1;
            if (match[q[x][i]] == -1 || dfs(match[q[x][i]])) {
                match[q[x][i]] = x;
                return 1;
            }
        }
    }
    return 0;
}
int main() {
    freopen("c.in", "r", stdin);
    freopen("c.out", "w", stdout);
    GetPrime_1();
    primes[1] = 0;
    int t = read();
    for (int cas = 1; cas <= t; cas++) {
        memset(match, -1, sizeof(match));
        int n = read();
        for (int i = 0; i < n; i++)
            q[i].clear();
        for (int i = 0; i < n; i++)
            a[i] = read();
        sort(a, a + n, cmp);
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                if (i == j)
                    continue;
                int b = a[j];
                int c = a[i];
                if (b < c)
                    swap(b, c);
                if (b % c == 0 && primes[b / c]) {
                    q[j].push_back(i);
                }
            }
        }
        int ans = 0;
        for (int i = 0; i < n; i++) {
            memset(vis, 0, sizeof(vis));
            if (dfs(i))
                ans++;
        }
        printf("%d\n", n - ans / 2);
    }

}

总结(讲垃圾话)

一二题其实都很蠢(但是我每道题都玩掉了40分)
三题不算难。

看着佘刀AK虐场只能望洋兴叹。

Doggu学长对我们提出的几点期望,我竟然完美的完全没有做到。

还有90天就是NOIP了,希望自己脚踏实地,砥砺奋斗,踏浪前行。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值