1级算法水一波,希望坚持下去…
1001 数组中和等于K的数对
给出一个整数K和一个无序数组A,A的元素为N个互不相同的整数,找出数组A中所有和等于K的数对。例如K = 8,数组A:{-1,6,5,3,4,2,9,0,8},所有和等于8的数对包括(-1,9),(0,8),(2,6),(3,5)。
Input
第1行:用空格隔开的2个数,K N,N为A数组的长度。(2 <= N <= 50000,-10^9 <= K <= 10^9)
第2 - N + 1行:A数组的N个元素。(-10^9 <= A[i] <= 10^9)
Output
第1 - M行:每行2个数,要求较小的数在前面,并且这M个数对按照较小的数升序排列。
如果不存在任何一组解则输出:No Solution。
Input示例
8 9
-1
6
5
3
4
2
9
0
8
Output示例
-1 9
0 8
2 6
3 5
QY的方法,首尾两个指针相互逼近,比二分快多了。
#include <iostream>
#include <cstring>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <queue>
using namespace std;
const int inf = 0x7fffffff;
const int maxn=50000+5;
int a[maxn];
int main ()
{
int m,n;
cin>>m;
cin>>n;
for(int i=0;i<n;i++){
cin>>a[i];
}
sort(a,a+n);
int i=0,j=n-1;
int flag=1;
while(j>i){
if(a[i]+a[j]>m){
j--;
}else if(a[i]+a[j]<m){
i++;
}else{
flag=0;
cout<<a[i]<<" "<<a[j]<<endl;
i++;
j--;
}
}
if(flag){
cout<<"No Solution"<<endl;
}
return 0;
}
1003 阶乘后面0的数量
n的阶乘后面有多少个0?
6的阶乘 = 1*2*3*4*5*6 = 720,720后面有1个0。
Input
一个数N(1 <= N <= 10^9)
Output
输出0的数量
Input示例
5
Output示例
1
2*5=10 可得0 ,知道2的数量一定大于5的数量只要求因数5的个数了。
#include <iostream>
#include <cstring>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <queue>
using namespace std;
const int inf = 0x7fffffff;
const int maxn=500+5;
int a[maxn][maxn];
int dp[maxn][maxn];
int main ()
{
int n;
cin>>n;
int sum=0;
while(n){
n/=5;
sum+=n;
}
cout<<sum<<endl;;
return 0;
}
1091 线段的重叠
X轴上有N条线段,每条线段包括1个起点和终点。线段的重叠是这样来算的,[10 20]和[12 25]的重叠部分为[12 20]。
给出N条线段的起点和终点,从中选出2条线段,这两条线段的重叠部分是最长的。输出这个最长的距离。如果没有重叠,输出0。
Input
第1行:线段的数量N(2 <= N <= 50000)。
第2 - N + 1行:每行2个数,线段的起点和终点。(0 <= s , e <= 10^9)
Output
输出最长重复区间的长度。
Input示例
5
1 5
2 4
2 8
3 7
7 9
Output示例
4
贪心了,做这道题就想起LZX学长讲课
#include <iostream>
#include <cstring>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <queue>
using namespace std;
const long long maxn=50000+100;
struct Line{
int l;
int r;
}L[maxn];
bool cmp(Line A,Line B){
if(A.l==B.l){
return A.r<B.r;
}
return A.l<B.l;
}
int main(){
int n;
cin>>n;
int i=0;
for(int i=0;i<n;i++){
cin>>L[i].l>>L[i].r;
}
sort(L,L+n,cmp);
int Max=0,t=0;
int ll=L[0].l,rr=L[0].r;
for(int i=1;i<n;i++){
if(L[i].l<L[i-1].r){//chongdie
ll=L[i].l;
// cout<<"ll="<<ll<<endl;
t=min(L[i].r,rr)-ll;
// cout<<t<<endl;
rr=max(L[i].r,rr);
Max=max(t,Max);
}
}
cout<<Max<<endl;
return 0;
}
1284 2 3 5 7的倍数
给出一个数N,求1至N中,有多少个数不是2 3 5 7的倍数。 例如N = 10,只有1不是2 3 5 7的倍数。
Input
输入1个数N(1 <= N <= 10^18)。
Output
输出不是2 3 5 7的倍数的数共有多少。
Input示例
10
Output示例
1
忘记了容斥原理的我,傻傻的被10^18折磨了好久。。。
数分类 2 3 5 7中单一元素的倍数,两个、三个、四个元素的倍数,之间有重复计算的情况。
直接计算n -(2 3 5 7)+( 6 10 14 15 21 35)-(30 42 70 105)+ 210 的倍数
#include <iostream>
#include <cstring>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <queue>
using namespace std;
const long long maxn=10000+100;
const int INF=0xfffffff;
long long sum=0;
int main (){
long long n;
cin>>n;
sum+=(n/2+n/3+n/5+n/7);
sum-=(n/6+n/10+n/14+n/15+n/21+n/35);
sum+=(n/30+n/42+n/70+n/105);
sum-=n/210;
cout<<n-sum<<endl;
return 0;
}
1289 大鱼吃小鱼
有N条鱼每条鱼的位置及大小均不同,他们沿着X轴游动,有的向左,有的向右。游动的速度是一样的,两条鱼相遇大鱼会吃掉小鱼。从左到右给出每条鱼的大小和游动的方向(0表示向左,1表示向右)。问足够长的时间之后,能剩下多少条鱼?
Input
第1行:1个数N,表示鱼的数量(1 <= N <= 100000)。
第2 - N + 1行:每行两个数A[i], B[i],中间用空格分隔,分别表示鱼的大小及游动的方向(1 <= A[i] <= 10^9,B[i] = 0 或 1,0表示向左,1表示向右)。
Output
输出1个数,表示最终剩下的鱼的数量。
Input示例
5
4 0
3 1
2 0
1 0
5 0
Output示例
2
在没有想到模拟栈之前,准备用一个很复杂的方法来学,但是自己在那个方法中绕晕了,最后一想,就是直接栈嘛。
#include <iostream>
#include <cstring>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <queue>
#include <stack>
using namespace std;
const long long maxn=100000+100;
const int INF=0xfffffff;
int main()
{
stack<int>St;
while(!St.empty()){
St.pop();
}
int n;
cin>>n;
int flag=1;
int ans=0;
while(n--){
int x,y;
cin>>x>>y;
if(St.empty()&& y==0){
ans++;
continue;
}
if(y){
St.push(x);
continue;
}
while(!St.empty()){
int t=St.top();
if(t<x){
St.pop();
}
if(t>x){
break;
}
}
if(St.empty()){
ans++;
}
}
while(!St.empty()){
ans++;
St.pop();
}
cout<<ans<<endl;
return 0;
}
1305 Pairwise Sum and Divide
有这样一段程序,fun会对整数数组A进行求值,其中Floor表示向下取整:
fun(A)
sum = 0
for i = 1 to A.length
for j = i+1 to A.length
sum = sum + Floor((A[i]+A[j])/(A[i]*A[j]))
return sum
给出数组A,由你来计算fun(A)的结果。例如:A = {1, 4, 1},fun(A) = [5/4] + [2/1] + [5/4] = 1 + 2 + 1 = 4。
Input
第1行:1个数N,表示数组A的长度(1 <= N <= 100000)。
第2 - N + 1行:每行1个数A[i](1 <= A[i] <= 10^9)。
Output
输出fun(A)的计算结果。
Input示例
3
1 4 1
Output示例
4
很明显伪代码的时间复杂度跑不出来。所以找捷径(规律)咯。
a+b>=a*b 这种事情只能发生在1 和2 上面。所以直接统计1 和2 的数目就好了。
#include <iostream>
#include <cstring>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <queue>
using namespace std;
const long long maxn=100000+100;
const int INF=0xfffffff;
int a[maxn];
int main (){
int n;
cin>>n;
int sum1=0;
int sum2=0;
for(int i=0;i<n;i++){
cin>>a[i];
if(a[i]==1){
sum1++;
}else if(a[i]==2){
sum2++;
}
}
long long ans=sum1*(sum1-1);
ans+=(sum2*(sum2-1))/2;
ans+=sum1*(n-sum1);
cout<<ans;
return 0;
}
1347 旋转字符串
S[0…n-1]是一个长度为n的字符串,定义旋转函数Left(S)=S[1…n-1]+S[0].比如S=”abcd”,Left(S)=”bcda”.一个串是对串当且仅当这个串长度为偶数,前半段和后半段一样。比如”abcabc”是对串,”aabbcc”则不是。
现在问题是给定一个字符串,判断他是否可以由一个对串旋转任意次得到。
Input
第1行:给出一个字符串(字符串非空串,只包含小写字母,长度不超过1000000)
Output
对于每个测试用例,输出结果占一行,如果能,输出YES,否则输出NO。
Input示例
aa
ab
Output示例
YES
NO
这题 就是比较 i 和 i+len/2 位置上的字符是否相同嘛。记得%len.
#include <iostream>
#include <cstring>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <queue>
using namespace std;
const long long maxn=1000000+100;
const int INF=0xfffffff;
int main (){
char S[maxn];
cin>>S;
int len=strlen(S);
for(int i=0;i<len;i++){
int t=(i+len/2)%len;
if(S[i]!=S[t]){
cout<<"NO"<<endl;
return 0;
}
}
cout<<"YES"<<endl;
return 0;
}