算法普及1
初识复杂度
时间复杂度表示程序运行占用时间的多少,是评估算法效率的重要指标。一般表示为关于 n 的某个函数。其中 n 往往对应输入数据的规模,用 T(n) 表示。
若有某个辅助函数 f(n) ,存在一个正常数 c 使得 f(n)×c>=T(n) 恒成立。记作 T(n)=O(f(n)) ,称 O(f(n)) 为算法的渐进时间复杂度,简称时间复杂度。
时间复杂度常用大 O 符号表述,不包括这个函数的低阶项和首项系数。
运行效率由低到高:
O(nn)>O(n!)>O(kn)>O(nk)>O(n n \sqrt{n} n)>O(nlog(n))>O(n)>O( n \sqrt{n} n)>O(log(n))>O(1)
t4:
最小周长
一个矩形的面积为S,已知该矩形的边长都是整数,求所有满足条件的矩形中,周长的最小值。例如:S = 24,那么有{1 24} {2 12} {3 8} {4 6}这4种矩形,其中{4 6}的周长最小,为20。
输入格式
输入1个数S(1 <= S <= 10^9)。
输出格式
输出最小周长。
输入样例
20
输出样例
20
思路
即求s被分解成两个最相近的整数的乘积
从1到
s
\sqrt{s}
s包含了其中一边的长度
为了使相邻两边差最小,从
s
\sqrt{s}
s开始向1找
代码
#include<bits/stdc++.h>
using namespace std;
int n;
int main(){
scanf("%d",&n);
for(int i=sqrt(n);i>=1;i--)
if(n%i==0){
printf("%d",2*((n/i)+i));
return 0;
}
}
时间复杂度为O( n \sqrt{n} n)
和为K的倍数
小b喜欢和为K的倍数的序列。
现在有一个长度为n的序列A,请问A有多少个非空连续子序列是小b喜欢的。
输入格式
第一行输入一个正整数n; 第二行输入n个整数,表示A[i],以空格隔开; 第三行输入一个正整数K; 其中1≤n≤30000,对于任意A[i]有-10000≤A[i]≤10000,2≤K≤10000
输出格式
输出一个数,表示子序列的数目
输入样例
6
4 5 0 -2 -3 1
5
输出样例
7
思路
求连续非空子序列的话可以想到用前缀和
如果枚举的话还是O(n2)
如果(ai-aj)%k则ai%k-aj%k=0
对于每一种余数的情况,只用Cn2就可以算出
前缀和算上第0个数便于计算(ai-0)就是从a1加到ai
代码
#include<cstdio>
int n,k,t,a[30005],sum=0,cnt[10005];
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&t);
a[i]=a[i-1]+t;
}
scanf("%d",&k);
for(int i=0;i<=n;i++)
cnt[(a[i]%k+k)%k]++;//防止负数越界,统计每种余数的数量
for(int i=0;i<k;i++)
sum+=(cnt[i]-1)*cnt[i]/2;
printf("%d",sum);
}
时间复杂度为O(n+k)
数字1的数量
给定一个十进制正整数N,写下从1开始,到N的所有正数,计算出其中出现所有1的个数。
例如:n = 12,包含了5个1。1,10,12共包含3个1,11包含2个1,总共5个1。
输入格式
输入N(1 <= N <= 10^9)
输出格式
输出包含1的个数
输入样例
12
输出样例
5
思路
O(n)肯定不行,可以考虑每一位的1出现的次数
如果当位数字大于等于2
----------------------------------------------------------------------------------------------------------------------


浙公网安备 33010602011771号