20181005提高测试

Posted lstoi

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了20181005提高测试相关的知识,希望对你有一定的参考价值。

T1: 阶乘
fact.cpp
【问题描述】
有 n个正整数 a[i],设它们乘积为 p,你可以给 p乘上一个正整数 q,使 p*q刚好为正
整数m的阶乘,求m的最小值。
【输入】
共两行。
第一行一个正整数n。
第二行n个正整数a[i]。
【输出】
共一行
一个正整数m。
【输入样例】
1
6
【输出样例】
3

样例解释:
当p=6,q=1时,p*q=3!

【数据范围与约定】
对于10%的数据,n<=10
对于30%的数据,n<=1000
对于100%的数据,n<=100000,a[i]<=100000

【错解】

首先猜想和最大值有关,然而样例都凑不出来

然后开始瞎搞,从大往小拆成两个没出现过的数的乘积

过了样例……

等等?好像最大有重复的?

然后真瞎搞

WA1+TLE9

期间想到二分,但并不知道怎么check,索性放弃

【正解】

二分

由于是阶乘,x!某个因数a出现次数为

(sum _{i=1}^{infty} [frac{x}{a^{i}}])

把读入的数分解,然后就可以check辣

#include <iostream>
#include <cstdio>
#include <cctype>
#define MAXN 100005
#define MAX  100000
#define int long long
using namespace std;
int np[MAXN];
int p[MAXN],t[MAXN],tot,pr[MAXN];
inline int read()
{
    int ans=0,f=1;
    char c=getchar();
    while (!isdigit(c))
    {
        if (c=='-')
            f=-1;
        c=getchar();
    }
    while (isdigit(c))
        ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
    return f*ans;
}
void write(int x)
{
    if (x<0)
        putchar('-'),x=-x;
    if (x<10)
    {
        putchar(x^48);
        return;
    }
    write(x/10);
    putchar((x%10)^48);
}
void getprime()
{
    np[1]=1;
    for (int i=2;i<=MAX;i++)
    {
        if (!np[i])
        {
            p[++tot]=i;
            pr[i]=tot;
            
        }
        for (int j=1;j<=tot&&i*p[j]<=MAX;j++)
        {
            np[i*p[j]]=1;
            if (i%p[j]==0)
                break;
        }
    }
}
void depart(int x)
{
    if (pr[x])
    {
        t[pr[x]]++;
        return;
    }
    int tx=x;
    for (int i=2;i<=tx;i++)
        while (tx%i==0)
        {
            tx/=i;
            t[pr[i]]++;
        }
}
bool check(int x)
{
    for (int i=1;i<=tot;i++)
    {
        int tx=x;
        int sum=0;
        while (tx)
        {
            tx/=p[i];
            sum+=tx;
        }
        if (sum<t[i])
            return false;
    }
    return true;
}
main()
{
    freopen("fact.in","r",stdin);
    freopen("fact.out","w",stdout);
    getprime();
    int n=read();
    for (int i=1;i<=n;i++)
        depart(read());
    int l=0,r=1e8;
    while (l<r)
    {
        int mid=(l+r)>>1;
        if (check(mid))
            r=mid;
        else
            l=mid+1;
    }   
    write(l);
    return 0;
} 

T2:上升序列
(lis)
【问题描述】
给出一个长度为 m 的上升序列 A(1 ≤ A[i]≤ n), 请你求出有多少种 1...n 的排列, 满足
A 是它的一个 LIS.
【输入】
第一行两个整数 n,m.
接下来一行 m 个整数, 表示 A.
【输出】
一行一个整数表示答案.
【输入样例1】
5 3
1 3 4
【输出样例1】
11
【输入样例2】
4 2
3 4
【输出样例2】
5
【数据范围与约定】
对于前 30% 的数据, n ≤ 9;
对于前 60% 的数据, n ≤ 12;
对于 100% 的数据, 1 ≤ m ≤ n ≤ 15.

【错解】

一看数据范围就知道是暴搜

发现没有规律,怒写了个nlogn暴力check

用链表维护

没有减掉枝

AC6+TLE4

【正解】

为什么不能状压呢

首先回忆nlogn求法:

定义d[i]为结尾最小的LIS,然后二分插入来转移

即nlogn求时最后的那个数组

当然不是这么做的

设状态s表示选了那些数,s1表示d中哪些数出现了

举个生动形象的栗子:2 3 1 4……

s={1,1,1,1,0}

d={1,4}

s1={1,0,0,1,0}

因为d是单调增的,所以我们可以用s1来还原d

即如果s1[i]为1,那么i在d中出现的位置为1~i的1的个数

然后可以(f(s,s1))定义状态

然后枚举插入一个数,就可以转移了

具体操作:插入i时,前面有k位

s|=i

s1前k位转成d,再把后面接上

如在3、1之间插入5

s={1,1,1,1,1}

s1不变

边界:当s为全集时,(f(s,s1)=(d长度为原序列长度))

然而复杂度不可接受

观察发现s1为s子集

所以可以三进制表示:0表示都不在,1表示在s不在s1,2表示既在s又在s1

然后可以AC此题

[代码待补]

相遇
(meet)
【问题描述】
豪哥生活在一个 n 个点的树形城市里面,每一天都要走来走去。虽然走的是比较的
多,但是豪哥在这个城市里面的朋友并不是很多。
当某一天,猴哥给他展现了一下大佬风范之后,豪哥决定要获得一些交往机会来提升交
往能力。豪哥现在已经物色上了一条友,打算和它(豪哥并不让吃瓜群众知道性别)交
往。豪哥现在 spy 了一下这个人的所有行程起点和终点,豪哥打算从终点开始走到起点与
其相遇。但是豪哥是想找话题的,他想知道以前有多少次行程和此次行程是有交集的,这
样豪哥就可以搭上话了。这个路径与之前路径的有交集数量作为豪哥此次的交往机会。
但是豪哥急着要做交往准备,所以算什么交往机会的小事情就交给你了。
【输入】
第一行一个正整数 n表示节点个数。接下来 n-1行,每行两个正整数分别是 u,v表示节点
u和 v之间有连边。接下来一行一个 正整数 m表示路径个数。然后有 m行,每行两个正整
数分别是u,v分别表示 u到v之间有一条路径。
【输出】
输出共m行,每行一个整数,第 i行表示豪哥在这条路径上获得的交往机会。
【输入样例】
5
1 2
1 3
3 4
3 5
4
4 5
4 2
1 3
1 2
【输出样例】
0
1
2
2
【数据范围与约定】
对于20%的数据n,m≤2000
对于另外20%的数据n,m≤50000
对于另外10%的数据n,m≤200000保证树形结构是一条链
对于另外50%的数据n,m≤200000

【错解】

woc提高考树剖?还没法维护?

骗分,放弃

WA10

【正解】

一个结论:树上两条路径有交集,当且仅当其中一条路径的LCA在另一条路径上

然后就转化为:

单点修改,路径查值

路径修改,单点查值

然后直接上树链……什么?被卡了?

考虑路径可以转换为4个点到根路径,做个类似于树上前缀和的玩意

然后直接上树剖

因为是单点查值,到根路径对其有影响当且仅当在其子树上

然后成了子树 树状数组维护dfs序即可

[代码待补]

以上是关于20181005提高测试的主要内容,如果未能解决你的问题,请参考以下文章

test20181005 序列

论“浏览器”-20181005

20181005 js数组去重的三种方法

20181005 PHP 中 echo ,print,vardump 语句区别

Linux就该这么学 20181005(第八章防火墙)

Linux就该这么学 20181005(第七章磁盘管理)