13th.Feb.2019

2023-12-02 01:10
文章标签 13th feb.2019

本文主要是介绍13th.Feb.2019,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

13th.Feb.2019

T1

...
好像问题挺简单的,来看看数据范围吧……
..
有没有点刚开始很欣喜后来有些恼火的感觉?那就对啦

:诶,这题我会n^2写法,20分呀,啊哦

:诶,我傻了,每个数求一下因数,n*sqrt(n)可以写。(看下数据范围,还是20)

:啊!我想到了nlogn的写法!!(看一下数据范围,这尼玛怎么还是20啊~~)

蒟蒻实在想不到更优秀的算法了,就先讲一下我们nlogn的“优秀”算法吧。

算法一:倍数筛筛筛
  • 注意,我们之前在每个数都进行根号求因数的时候,其实重复了很多次。就是说你枚举根号n个数里面有很多数不是因数,没有什么用。我们要充分利用每一个数,减少不必要的枚举。所以,应该考虑每个数能对哪些数产生贡献。

  • 如果当前数的因数个数确定了,那么它能产生的所有贡献都在是它的整数倍的数上。因此我们可以枚举当前数的所有倍数,把它的因数个数加到这个倍数的答案里。

  • 那么我们如何知道当前数的因数个数呢?还要根号n求吗?其实不然,如果按照我们刚才说的筛法,我们对每个数再记录一下它被筛到的次数,那么当你递推到当前数的时候,你已经知道了它的因数个数,就是被筛的次数+1(1是它本身)。

  • 复杂度怎么算?

    ​ 每一个数枚举倍数,复杂度是n/i的,那么就是n/1+n/2+n/3+n/4+......+n/n,有同学说有点像n^2,别急。把n提出来,变成n*(1+1/2+1/3+1/4+...+1/n),(1+1/2+1/3+1/4+...+1/n)是调和级数,我们可以认为它是log的复杂度,因此本做法复杂度nlogn。

  • 可是明明利用每个数那么充分了,怎么还是20分啊QAQ。说明我们的思路需要转化。(不过如果需要打表的同学,本算法算是最优秀的了)。

算法二:暴力出奇迹!分块打表
  • 1e7内的答案我们可以在下面自己打出来,用上面的算法短时间内可以算出。不过1e7的数据肯定不能直接存入代码打表了,毕竟得1万行,100Mb左右(一位同学亲自试验)。
  • 所以考虑分块打表,我们每隔5000个数,记录一个答案,这样的话,你对于1e7的数据,只需要存2000个数,是没问题的。然后块外面的数对答案的影响,直接暴力求没有问题吧,毕竟最多5000个数,你nsqrt(n)也是可以的。
  • 60的高分喽
算法三:转化——三元组个数
  • 先看一下d(p),它是不是可以转化成这样:∑(p%f==0),也就是f*k=p这样的二元组的个数,并且二元组有序。
  • 然后∑d(p)是不是类似的,因为是连加的每一个p|i,所以其实是x * y * z=i这样的有序三元组的个数。
  • 然后i从1~n,所以题目所求就是x * y * z <= n的有序三元组的个数。
  • 不妨设x<=y<=z,那么x的范围在n^(1/3)内,y的范围则在sqrt(n/x)内。这样我们可以枚举了吧,枚举每一个x,然后枚举y,z有多少个自然可以求出来,累加到ans里。(注意使z>=y)。
  • 因为刚才的是递增的,而三元组有6中排列,所以乘6.
  • 但是有多计算的,比如说有两个数相同的三元组,只有三种排列,所以需要减去三倍。还有三个数相同的三元组,只有一种排列,所以减去五倍。
  • 到此为止,本题做完了。是不是感觉一步一步推出来还挺有意思的?(考场快急哭了,有意思)。
Coding
#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll n,x,y,z;ll ans; //wa的教训告诉我一定全部变量使用longlong
int main(){freopen("divisor.in","r",stdin);freopen("divisor.out","w",stdout);scanf("%lld",&n);ll l=pow(1.0*n,0.33333333)+1; //毒瘤题目卡精度,多加几个3ll r;for(x=1;x<=l;++x){r=sqrt(1.0*(1.0*n/x))+1;for(y=x;y<=r;++y){z=n/(x*y);while(x*y*z>n) z--;if(z>=y){ans+=1LL*(z-y+1)*6;}}}r=sqrt(1.0*n)+1;for(x=1;x<=r;++x){z=n/(x*x);if(z>0){if(z>=x) ans-=1LL*(z-1)*3;else ans-=1LL*z*3;}}for(x=1;x<=l;++x){int temp=x*x*x;if(temp<=n) ans-=5;}printf("%lld\n",ans);return 0;
}

T2和T3不太会啊,不是很可做

speech.gif posted on 2019-02-14 20:32 kgxpbqbyt 阅读( ...) 评论( ...) 编辑 收藏

这篇关于13th.Feb.2019的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/443391

相关文章

【ZOJ3940 The 13th Zhejiang Provincial Collegiate Programming ContestE】【脑洞 STL-MAP 复杂度分析 区间运算思想 双指针】M

Modulo Query Time Limit: 2 Seconds      Memory Limit: 65536 KB One day, Peter came across a function which looks like: F(1, X) = X mod A1.F(i, X) = F(i - 1, X) mod Ai, 2 ≤ i ≤ N. Where

UE4学习笔记13th:使用C++ 代码以对输入进行响应

这节对输入进行响应。 首先打开PawnWithCamera.h添加定义: //输入变量FVector2D MovementInput;FVector2D CameraInput;float ZoomFactor;bool bZoomingIn; 紧接着创建函数来追溯输入: //输入函数void MoveForward(float AxisValue);void MoveRin

13th day

目录 P291 课程介绍与知识点回顾 P292 指针与函数  1. 指针作为函数的参数.  2. 指针作为函数的返回值  3.注意 P293 案例讲解  4. 案例  5. 申请在常量区的空间.不会被回收的. P294 指向函数的指针  1. 我们之前学习的指针.  2. 程序在运行的时候. 会将程序加载到内存.     优势: 调用函数有了两种方式.  3. 指向函

正则表达式(13th)

今天想了很多开题思路和仔细分析琢磨了开题第一个点,前端这里学的慢了,明天一定要把JavaScript高级学完,之后开启两周的vue学习 1 正则表达式概述 1.1 什么是正则表达式 正则表达式( Regular Expression )是用于匹配字符串中字符组合的模式。在 JavaScript中,正则表达式也是对象。 正则表通常被用来检索、替换那些符合某个模式(规则)的文本,例如验证

The 13th Zhejiang Provincial Collegiate Programming Contest (杂谈)

明天就要和大家一起出发去杭州了。此刻心情是 不安 。 第一次参加如此正式的比赛。 算起来,在CSDN写博客也差不多快一个月了。这一个月也算是有很大的进步吧。 在一个月前,自己还是连STL甚至是一些如strcmp函数都还不知道的菜鸟(虽然现在也是菜鸟。。)。 一个月前自己可能也为自己能写出一些小小的辣鸡程序而洋洋得意。现在看来,颇有一丝井底蛙的感觉。 盗用某人的话:要是我没加ACM,也许还

DEPRECATION: Python 3.5 reached the end of its life on September 13th, 2020

这几天打开spyder运行,发现之前装的库都用不了了,就想重新配置一下,输入命令行之后就发现了这个: DEPRECATION: Python 3.5 reached the end of its life on September 13th, 2020. Please upgrade your Python as Python 3.5 is no longer maintained. pip 21

The 13th UESTC Programming Contest Preliminary——Hug the princess

题意:根据公式进行计算。 解题思路:首先,自己可以通过举几个例子来验证,异或运算与与运算之和刚好等价于或运算,或者可以这样想,异或是(1,0)、(0,1),与是(1,1),合起来刚好是或。然后题目就是求两倍的或运算了。然后,每一个ai都与aj或运算(i<j),每次ai与aj或的时候,aj二进制位上是1的数位在或运算后总还是1,所以前面有多个ai与aj或,最后结果里就有多少个aj的和;然后考虑aj

The 13th UESTC Programming Contest Preliminary——Hug the princess

题意:根据公式进行计算。 解题思路:首先,自己可以通过举几个例子来验证,异或运算与与运算之和刚好等价于或运算,或者可以这样想,异或是(1,0)、(0,1),与是(1,1),合起来刚好是或。然后题目就是求两倍的或运算了。然后,每一个ai都与aj或运算(i<j),每次ai与aj或的时候,aj二进制位上是1的数位在或运算后总还是1,所以前面有多个ai与aj或,最后结果里就有多少个aj的和;然后考虑aj