寒假做题记录

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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值