• D. Infinite Set 题解(思维+dp)


    题目链接

    题目思路

    首先要观察它需要的数是小于\(2^p\),那么需要往二进制的思路去想就简单很多

    \(x=2y+1\) 本质上就是在二进制的表现下末尾加一个1

    \(x=4y\) 本质上就是在二进制的表现下末尾加两个\(00\)

    那么如果一个二进制长度为\(len\)的数\(x\)

    它要延申成长度为\(len+1\)位有\(1\)

    它要延申成长度为\(len+2\)位有\(2\)

    它要延申成长度为\(len+3\)位有\(3\)

    这就是斐波那契数列

    定义\(\sum_{i=0}^{i=n} fac[i]=sum[n]\)

    那么如果他要延申成长度小于\(p\)位有\(sum[p-len]\)

    那么对于一个数的情况解决了,那么对于多个数的情况就是需要去重

    加入\(x\)可以生成\(y\),那么需要去掉\(y\)

    那么假如\(y\)是奇数,\(y/=2\) 。假如\(y\)\(4\)的倍数,\(y/=4\) 看中途是否出现过即可

    代码

    #include<bits/stdc++.h>
    #define fi first
    #define se second
    #define debug cout<<"I AM HERE"<<endl;
    using namespace std;
    typedef long long ll;
    const int maxn=2e5+5,inf=0x3f3f3f3f,mod=1e9+7;
    const double eps=1e-6;
    int n,p;
    int a[maxn];
    ll ans;
    ll fac[maxn],sum[maxn];
    map<int, bool> mp;
    int cal(int x){
        int len=0;
        while(x){
            x/=2;
            len++;
        }
        return len;
    }
    signed main(){
        fac[0]=fac[1]=1;
        sum[0]=1;
        sum[1]=2;
        for(int i=2;i<=2e5;i++){
            fac[i]=(fac[i-1]+fac[i-2])%mod;
            sum[i]=(sum[i-1]+fac[i])%mod;
        }
        scanf("%d%d",&n,&p);
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
            mp[a[i]]=true;
        }
        for(int i=1;i<=n;i++){
            int tmp=a[i];
            bool flag=false;
            while(tmp){
                if(tmp%2){
                    tmp/=2;
                }else if(tmp%4==0){
                    tmp/=4;
                }else{
                    break;
                }
                if(mp.count(tmp)){
                    flag=true;
                    break;
                }
            }
            if(flag) continue;
            int len=cal(a[i]);
            if(p-len>=0){
                ans=(ans+sum[p-len])%mod;
            }
        }
        printf("%lld\n",ans);
        return 0;
    }
    

    题目链接

    题目思路

    首先要观察它需要的数是小于\(2^p\),那么需要往二进制的思路去想就简单很多

    \(x=2y+1\) 本质上就是在二进制的表现下末尾加一个1

    \(x=4y\) 本质上就是在二进制的表现下末尾加两个\(00\)

    那么如果一个二进制长度为\(len\)的数\(x\)

    它要延申成长度为\(len+1\)位有\(1\)

    它要延申成长度为\(len+2\)位有\(2\)

    它要延申成长度为\(len+3\)位有\(3\)

    这就是斐波那契数列

    定义\(\sum_{i=0}^{i=n} fac[i]=sum[n]\)

    那么如果他要延申成长度小于\(p\)位有\(sum[p-len]\)

    那么对于一个数的情况解决了,那么对于多个数的情况就是需要去重

    加入\(x\)可以生成\(y\),那么需要去掉\(y\)

    那么假如\(y\)是奇数,\(y/=2\) 。假如\(y\)\(4\)的倍数,\(y/=4\) 看中途是否出现过即可

    代码

    #include<bits/stdc++.h>
    #define fi first
    #define se second
    #define debug cout<<"I AM HERE"<<endl;
    using namespace std;
    typedef long long ll;
    const int maxn=2e5+5,inf=0x3f3f3f3f,mod=1e9+7;
    const double eps=1e-6;
    int n,p;
    int a[maxn];
    ll ans;
    ll fac[maxn],sum[maxn];
    map<int, bool> mp;
    int cal(int x){
        int len=0;
        while(x){
            x/=2;
            len++;
        }
        return len;
    }
    signed main(){
        fac[0]=fac[1]=1;
        sum[0]=1;
        sum[1]=2;
        for(int i=2;i<=2e5;i++){
            fac[i]=(fac[i-1]+fac[i-2])%mod;
            sum[i]=(sum[i-1]+fac[i])%mod;
        }
        scanf("%d%d",&n,&p);
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
            mp[a[i]]=true;
        }
        for(int i=1;i<=n;i++){
            int tmp=a[i];
            bool flag=false;
            while(tmp){
                if(tmp%2){
                    tmp/=2;
                }else if(tmp%4==0){
                    tmp/=4;
                }else{
                    break;
                }
                if(mp.count(tmp)){
                    flag=true;
                    break;
                }
            }
            if(flag) continue;
            int len=cal(a[i]);
            if(p-len>=0){
                ans=(ans+sum[p-len])%mod;
            }
        }
        printf("%lld\n",ans);
        return 0;
    }
    
  • 相关阅读:
    使用Spring Cloud Feign作为HTTP客户端调用远程HTTP服务
    聊聊高并发系统之限流特技
    Java程序员 必须掌握的 20+ 种 Spring 常用注解
    这20个核心技术,作为Java开发程序员,你一定要掌握
    40K刚面完Java岗,这些技术必须掌握
    Java 5,6,7,8,9,10,11新特性超详细总结
    小米程序员的忧虑:感觉互联网这两年要凉,想回家种地
    Java技术文档—Java中的运算符有哪些?
    Java笔记之数组,异常处理,集合知识要点
    Java学习笔记——IO流基础知识点整理
  • 原文地址:https://www.cnblogs.com/hunxuewangzi/p/15918294.html
Copyright © 2020-2023  润新知