ACM训练日记—12月31日

        明天是元旦,今天写写博客总结下这半周收获的一点点东西,另外,也纪念一年2017年的最后一天。有点伤感,有点不舍,但这就是时光,就是青春。每次到这个时候都倍加伤感,感觉虽然我挺笨,而且很蠢,但2017对我真的挺好。

        2017学到了许多新知识,度过了许多难忘而且美好的时光,有了点小进步,也认识了许多新朋友。虽然有的时候有些小懒惰,小迷茫,但最终还是找到了前进的方向和几分未来的信心。 每到这个时候,最想留住的是时光,可最留不住的也是时光,这一年发生的事简直就像电影,一幕一幕,一张一张。2017年,我选修了ACM程序设计基础课,开始了我的ACM之旅,也开启了一场难忘的旅行。虽然我属于比较笨的类型,但我至少可以自信的说,2017年我真的有进步,无论从专业知识还是acm,还是到我的为人处事,见识心智,都或多或少有许多进步,许多改变。想想acm和大学时光已经所剩无几,真的不能怠慢,要更加努力,更加扎实,更加积极。必须鼓足干劲,还有寒假集训,明年的比赛,我必须要有质的变化,质的进步。

        

       有点不太像理科生了,那么伤感。进入正题吧。整理一下几道比较重要的题。

牛客网练习赛9   E珂朵莉的数论题

珂朵莉想求:
第x小的正整数v使得其最小的质因数为质数y,即正好有x-1个[1,v-1]之内的正整数满足其最小的质因数为质数y。
若答案超过1000000000则输出0。

          拿到这道题一开始感觉就是容斥原理,因为可以用容斥原理dfs出1到n之内有多少以y为最小质因数的个数,然后感觉二分答案找出满足条件的上界。其实思路上也沾边了,但是还是实力太菜,最终没能做出来。

下面是我找到两位大佬的做法,思路大致也差不多。

void init()
{
    for(int i=2;i<=maxn;++i)//筛素数
    {
        if(!prime[i])prime[++prime[0] ]=i;
        for(int j=1;j<=prime[0]&&prime[j]<=maxn/i;++j)
        {
            prime[prime[j]*i]=1;
            if(i%prime[j]==0)break;
        }
    }
}
bool has(int a,int m)//这波暴力令我猝不及防,只是暴力的确实比较巧妙。其实好好算算那个数据大小并没有那么吓人
{
    for(int i=1;;++i)
    {
        if(prime[i]>=m)return false;
        if(a%prime[i]==0)return true;
    }
}
int get(int a,int b)
{
    int cnt=0;
    for(int i=a;i<=ma;i+=a)
    {
        ++cnt;
        if(has(i,a))--cnt;
        if(cnt==b)return i;
    }
    return 0;
}
int main()
{
    init();
    int m,n;cin>>m>>n;
    if(m==1)cout<<n;
    else
    {
        if((ll)n*n>ma)cout<<0;
        else
        {
            if(n<=3)//分类讨论2和3的情况,其他的直接暴力了,居然可以过
            {
                if(n==2)
                {
                    ll k=2;
                    if(k*m>ma)cout<<0;
                    else cout<<k*m;
                }
                else
                {
                    m=m*2-1;
                    ll k=3;
                    if(k*m>ma)cout<<0;
                    else cout<<k*m;
                }
            }
            else cout<<get(n,m);
        }
    }
    return 0;
}

下面这算是题解给出的做法

long long maxn=1000000000;
long long prime[20]={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71};
long long solve1()//y大于等于5直接时筛出来,方法也是挺巧妙的,这我这是没想到这有点暴力的做法居然可以,还是水平不行。

{
    long long i,j,k=1;
    if(x==1) return 1;
    for(i=2;i<y;i++) if(!p[i])
        for(j=i+i;j<=maxn;j+=i) p[j]=1;
    for(i=y;i<=maxn;i++){
        if(!p[i]){
            k++;
            if(x==k) return i;
        }
    }
    return 0;
}
long long cal(long long a,long long i)

{
    if(prime[i]>=y) return a;
    if(a==0) return 0;
    return cal(a,i+1)-cal(a/prime[i],i+1);
}
long long solve2()
{//当y为2,3,时用二分

    long long l=1,r=maxn,mid,sum;
    while(l<r){
        mid=(l+r)/2;
        sum=cal(mid,0);
        if(sum<x) l=mid+1;
        else r=mid;
    }
    if(x==cal(l,0)) return l;
    return 0;
}
int main(){
    scanf("%lld%lld",&x,&y);
    maxn/=y;
    if(y>=5) ans=solve1();
    else ans=solve2();
    printf("%lld\n",ans*y);
}

       又尝试水了几道期望题

A Dangerous Maze

题目大意: 给你n个门,每次进每个门的概率都是一样的,正数代表你x分钟后可以离开这里,负数代表你x分钟后回到这里。求预期离开的时间。

因为有走错门就失忆这个设定,所以可以直接列方程,解方程就可以,设期望是E,

E = (a1+a2+……+an + (abs(b1)+E)+(abs(b2)+E)+……+(abs(bm)+E))/n 整理得

E = (a1+a2+……+an+abs(b1)+abs(b2)+……+abs(bm))/(n-m);

其实就是解方程。

int gcd(int x,int y)
{
    if(y==0)
    {
        return x;
    }
    else return gcd(y,x%y);
}
int main()
{
   int T,n,x,Case=0;
   scanf("%d",&T);
   while(T--)
   {
       int cnt=0,sum=0;
       scanf("%d",&n);
       for(int i=1;i<=n;i++)
       {
           scanf("%d",&x);
           if(x<0) cnt++;
           sum+=abs(x);
       }
       cout<<"Case "<<++Case<<": ";
       if(cnt==n)//如果全是负数,那就走不出去了
       {
           cout<<"inf"<<endl;
           continue;
       }
       cnt=n-cnt;
       int k=gcd(sum,cnt);
       cout<<sum/k<<"/"<<cnt/k<<endl;
   }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值