zoukankan      html  css  js  c++  java
  • BZOJ3329

    题目

    1. 求出小于等于n的正整数中,多少数是(x oplus 3x = 2x)的解。
    2. 求出小于等于(2^n)的正整数中,多少数是(x oplus 3x = 2x)的解,模1e9+7。

    题解

    观察方程的解的性质,可以化成(x oplus 2x = 3x = (x + 2x))。异或有称作无进位的加,所以二进制表示下,x左移一位后不能和原来的x有相同的1,即x的没有连续的1。

    第一问用普通数位dp,第二问列出dp式可以发现就是Fibonacci数列。

    第二问一开始我脑抽搞错成求第(2^n)项,本想用通项+降幂,结果发现5在模1e9+7下不是二次剩余,即没有可以替代根号5的数。后来才发现n个二进制位,求第n项即可,这用矩阵加速就好了。

    #include <bits/stdc++.h>
    
    #define endl '
    '
    #define IOS std::ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
    #define FILE freopen(".//data_generator//in.txt","r",stdin),freopen("res.txt","w",stdout)
    #define FI freopen(".//data_generator//in.txt","r",stdin)
    #define FO freopen("res.txt","w",stdout)
    #define pb push_back
    #define mp make_pair
    #define seteps(N) fixed << setprecision(N) 
    typedef long long ll;
    
    using namespace std;
    /*-----------------------------------------------------------------*/
    
    ll gcd(ll a, ll b) {return b ? gcd(b, a % b) : a;}
    #define INF 0x3f3f3f3f
    
    const int N = 3e5 + 10;
    const int M = 1e9 + 7;
    const int M1 = M - 1;
    const int M2 = 533333328;
    const double eps = 1e-5;
    
    int di[N];
    ll n;
    ll f[N][2];
    
    struct Mat {
        ll arr[2][2];
        Mat() {
            memset(arr, 0, sizeof arr);
            arr[0][0] = arr[1][1] = 1;
        }
        Mat operator * (const Mat& rhs) const {
            Mat tmp;
            for(int i = 0; i < 2; i++) {
                for(int j = 0; j < 2; j++) {
                    tmp.arr[i][j] = 0;
                    for(int k = 0; k < 2; k++) {
                        tmp.arr[i][j] += arr[i][k] * rhs.arr[k][j] % M;
                        tmp.arr[i][j] %= M;
                    }
                }
            }
            return tmp;
        }
    
    };
    
    Mat mqpow(Mat a, ll b) {
        Mat res;
        while(b) {
            if(b & 1) res = res * a;
            a = a * a;
            b = b >> 1;
        }
        return res;
    }
    
    inline ll qpow(ll a, ll b, ll m) {
        ll res = 1;
        while(b) {
            if(b & 1) res = (a * res) % m;
            a = (a * a) % m;
            b = b >> 1;
        }
        return res;
    }
    
    ll dfs(int p, bool st, bool lmt) {
        if(!p) {
            return 1;
        }
        if(!lmt && f[p][st] >= 0) return f[p][st];
        ll res = 0;
        int maxx = lmt ? di[p] : 1;
        for(int i = 0; i <= maxx; i++) {
            if(st && i) continue;
            res += dfs(p - 1, i == 1, lmt && i == maxx);
        }
        if(!lmt) f[p][st] = res;
        return res;
    }
    
    ll solve(ll x) {
        int tot = 0;
        while(x) {
            di[++tot] = (x & 1);
            x >>= 1;
        }
        return dfs(tot, 0, 1);
    }
    
    int main() {
        IOS;
        memset(f, -1, sizeof f);
        int t;
        cin >> t;
        while(t--) {
            ll n;
            cin >> n;
            cout << solve(n) - 1 << endl;
            Mat ans;
            ans.arr[0][1] = 1;
            ans.arr[1][0] = 1;
            ans.arr[1][1] = 0;
            ans = mqpow(ans, n);
            cout << ((ans.arr[0][0] + ans.arr[0][1]) % M + M) % M << endl;
        }
    }
    
  • 相关阅读:
    kafka搭建
    kafaka学习笔记
    metastore 简单说明
    二 python并发编程之多进程-理论
    文件指针偏移量
    FTP
    1 并发编程
    操作系统简介
    1 网络编程
    网络编程-osi七层
  • 原文地址:https://www.cnblogs.com/limil/p/13537982.html
Copyright © 2011-2022 走看看