0205
0205-1
本乐色就是一道题搞了一个下午各种错都有。
看了题解才做出来
题目
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <string.h>
#include <cmath>
using namespace std;
#define MAX 1000000
long long n,re=1;
int ans=0,a[MAX+2]={0},j=0;
int main()
{
cin>>re;
while (re!=2)
{
n=re;
j=0;
memset(a,0,sizeof(a));
for(int i=2;i<=sqrt(n);i++)//这样做可以筛选出所有小于n的素数,因为素数的倍数大于该素数,在n%i的时候就会被筛掉,因为假如一个数字不是素数,那么它拆分出来的每个素数一定小于sqrt(n)
{
while(n%i==0)
{
a[j]++;
n/=i;
}
j++;
}
if(n!=1) n=2;//但是上面说了这样会导致如果n本身是素数,那么就筛不出来,所以这个用个if,把n为素数和n除到最后变成1的区分开
else n=1;
for(int i=0;i<j;i++)
{
n*=(a[i]+1);
}
re=n;
ans++;
}
printf("%d",ans);
return 0;
}
0205-2
题目
遍历的时候给26个字母都分好类,每个字母出现了几次以及每次出现的位置,最后遍历一下26个字母
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <string.h>
#include <cmath>
using namespace std;
struct node
{
int b[200005]={0};
int h=0;
}s[26];
int n,k,len,ans=200005,w;
char a[200005];
int main()
{
scanf("%d%d",&n,&k);
getchar();
gets(a);
len=strlen(a);
for(int i=0;i<len;i++)
{
s[a[i]-'a'].h++;
s[a[i]-'a'].b[s[a[i]-'a'].h-1]=i;
}
for(int i=0;i<26;i++)
{
if(s[i].h<k) continue;
else{
for(int j=0;j+k-1<s[i].h;j++)
{
w=s[i].b[j+k-1]-s[i].b[j]+1;
if(w<ans)
ans=w;
}
}
}
if(ans==200005)
printf("-1\n");
else
printf("%d\n",ans);
return 0;
}
0206
0206-1
题目
遍历,判断三点是否在一线上,再判断每个角的大小
#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;
const long long MAX=1e9+7;
int main()
{
int n,a[505][2],ans=0;
scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf("%d%d",&a[i][0],&a[i][1]);
}
for(int i=0;i<n;i++)
{
for(int j=i+1;j<n;j++)
{
for(int k=j+1;k<n;k++)
{
if((a[k][1]*a[j][0]+a[j][1]*a[i][0]+a[i][1]*a[k][0]-a[i][1]*a[j][0]-a[j][1]*a[k][0]-a[k][1]*a[i][0])
&&((a[j][0]-a[i][0])*(a[k][0]-a[i][0])+(a[j][1]-a[i][1])*(a[k][1]-a[i][1])<0||
(a[i][0]-a[j][0])*(a[k][0]-a[j][0])+(a[i][1]-a[j][1])*(a[k][1]-a[j][1])<0||
(a[j][0]-a[k][0])*(a[i][0]-a[k][0])+(a[j][1]-a[k][1])*(a[i][1]-a[k][1])<0))
ans++;
}
}
}
printf("%d\n",ans);
return 0;
}
0206-2
题目
如果不先判断pow的话会爆时间
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <cmath>
using namespace std;
const long long MAX=1e9+7;
int main()
{
int n,ans=0;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
int ii=pow(i,0.5)*100000;
if(ii%100000==0)
{
for(int j=1;j<=sqrt(i);j++)
{
if(i%j==0)
{
if(j*j==i)
ans++;
else ans+=2;
}
}
}
}
printf("%d\n",ans);
return 0;
}
0207
0207-1
题目:POJ3061
被T代码:
时间复杂度是n方 然后就被T了
#include <iostream>
#include <cstdio>
using namespace std;
int main()
{
int n,len,s,ss,ans,a[100005],re;
scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf("%d%d",&len,&s);
for(int i=0;i<len;i++)
scanf("%d",&a[i]);
ans=100005,ss=0;
for(int j=0;j<len;j++)
{
ss+=a[j];
if(ss>=s)
{
int sss=ss;
re=j+1;
for(int k=0;k<j;k++)
{
sss-=a[k];
if(sss>=s)
{
re--;
}
else break;
}
if(ans>re)
ans=re;
}
}
if(ans==100005) printf("0\n");
else printf("%d\n",ans);
}
return 0;
}
AC代码:
了解了一下尺取法
这里的时间复杂度是n(大概吧)
#include <iostream>
#include <cstdio>
using namespace std;
int main()
{
int n,len,s,ss,ans,a[100005],re,j,i,k;
scanf("%d",&n);
for(int k=0;k<n;k++)
{
scanf("%d%d",&len,&s);
for(i=0;i<len;i++)
scanf("%d",&a[i]);
ans=100005,ss=0;
for(j=0;j<len;j++)
{
ss+=a[j];
if(ss>=s)
{
ans=j+1;
break;
}
}
i=0;
if(ans==100005) printf("0\n");
else{
while(j<len-1||ss>=s)
{
if(ss>=s)
{
ss-=a[i];
i++;
}
else if(ss<s)
{
j++;
ss+=a[j];
}
if(ss>=s&&ans>j-i+1)
{
ans=j-i+1;
}
}
printf("%d\n",ans);
}
}
return 0;
}
0207-2
题目
看了题解,用尺取法做,(但是题解的代码并没完全看懂)
我的方法是先把操作机会全用完,如果没用完就已经扫描到最后一个字符了,那么结果就是输入字符串的长度,如果不是这种情况,那么操作次数必定会全部被用完。
然后从前往后看,现将不用变的字符剔除(不剔除无法往后扫描),然后要变化的字符导致l++,同时h++,随时保证s[h]是要变化的字符。
#include <iostream>
#include <cstdio>
using namespace std;
int n,k,ch,ans;
char s[200005];
int c(char a,char b)//a->b
{
ch=0;
int j=0,l=0,h=0,re;
while(ch<k&&h<n)
{
if(s[h]==a)
{
ch++;
h++;
}
else h++;
}
while(s[h]==b)
h++;
re=h-l;
while(h<n)
{
if(s[l]==b)
{
l++;
}
else
{
l++;
h++;
while(s[h]==b&&h<n)
h++;
}
if(re<h-l)
re=h-l;
}
return re;
}
int main()
{
scanf("%d%d",&n,&k);
getchar();
for(int i=0;i<n;i++) scanf("%c",&s[i]);
ch=0;
ans=max(c('0','1'),c('1','0'));
printf("%d\n",ans);
return 0;
}
0209
0209-1
题目:POJ3320
还是尺取法,用了map建立到知识点和数量的关系 map的key就是page,map的value就是代表key这个知识点出现的次数
#include <iostream>
#include <cstdio>
#include <set>
#include <string.h>
#include <map>
#include <algorithm>
using namespace std;
int p,book[1000005],sum,ans;
set<int> t,t1;
map<int,int> t2;
int main()
{
int j=0,l=0,h=0;
scanf("%d",&p);
for(int i=0;i<p;i++){
scanf("%d",&book[i]);
t.insert(book[i]);
}
sum=t.size();
ans=p;
while(h<p)
{
t1.insert(book[h]);
t2[book[h]]++;
h++;
if(t1.size()==sum)
{
while(t2[book[l]]>1)
{
t2[book[l]]--;
l++;
}
ans=min(ans,h-l);
}
}
printf("%d\n",ans);
return 0;
}
0210
0210-1
题目:POJ2566
这道题和上面一样也是尺取法,但不同的是,上面几道题的尺取法只需要直接从左往右取就可以了,而这道题则是现将数列的前缀和算出来再将前缀和排序进行尺取,只有这样才能保证“h++使得num增大,l++使得num减小”,复杂度为n。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <map>
using namespace std;
struct node{
int id;
int sum;
};
bool cmp(node x,node y)
{
return x.sum<y.sum;
}
int main()
{
int n,k,q,a;
while(scanf("%d%d",&n,&k)&&(n!=0||k!=0))
{
node n1[100005];
n1[0].id=0;
n1[0].sum=0;
for(int i=1;i<=n;i++){
scanf("%d",&q);
n1[i].id=i;
n1[i].sum=n1[i-1].sum+q;
}
sort(n1,n1+n+1,cmp);
for(int i=1;i<=k;i++)
{
scanf("%d",&a);
int j=1,k=0,l=0,h=0,d=2000000005,ans=0,num=0;
while(j<=n)
{
num=n1[j].sum-n1[k].sum;
if(abs(num-a)<d)
{
l=min(n1[j].id,n1[k].id);
h=max(n1[j].id,n1[k].id);
d=abs(num-a);
ans=num;
}
if(num>a)k++;
else if(num<a)j++;
else break;
if(j==k)j++;
}
printf("%d %d %d\n",ans,l+1,h);
}
}
return 0;
}
0211
0211-1
#include <iostream>
#include <string.h>
#include <cstdio>
using namespace std;
char a[1000005];
int c[1000005]={0},len,i,j;
int main()
{
gets(a);
len=strlen(a);
i=0,j=0;
while(len--)
{
if(a[i]=='(')
c[j]=1;
else if(a[i]==')')
c[j]=-1;
else if(a[i]=='{')
c[j]=2;
else if(a[i]=='}')
c[j]=-2;
else if(a[i]=='[')
c[j]=3;
else if(a[i]==']')
c[j]=-3;
if(c[j]+c[j-1]==0&&c[j]<0){
j-=2;
}
i++,j++;
}
if(j==0)
printf("Yes\n");
else printf("No\n");
return 0;
}