zoukankan      html  css  js  c++  java
  • GDCPC2021 B

    题目

    source

    题解

    方法一:
    可以知道,最多35位Fibonacci数列就可以表示1e7的数。可以发现,前23位表示的数存在大量重复。因此可以先预处理出前23位的结果,然后剩下12位和预处理结果暴力卷积。前23位预处理最大的数为75024,剩下4096的需要处理,故最多计算75024*4096=2e8。不过一遍到不了那么大,因此能过。

    #include<iostream>
    using namespace std;
    const int N = 1e7 + 10;
    const int M = 998244353;
    typedef long long ll;
    int mx;
    int f[40];
    int ans[N];
    int ans2[N];
    int s, mxv;
    void dfs(int p, int val, int res) {
        if(p >= mx) {
            mxv = max(mxv, val);
            ans[val] += res;
            ans[val] %= M;
            return ;
        }
        dfs(p + 1, val, res);
        dfs(p + 1, val + f[p], 1ll * res * f[p] % M);
         
    }
     
    void solve(int p, int val, int res) {
        if(val >= N) return ;
        if(p >= 35) {
            if(val)
                for(int i = 0; i <= mxv && val + i < N; i++) {
                    ans2[val + i] += 1ll * ans[i] * res % M;
                    ans2[val + i] %= M;
                }
            return ;
        }
        solve(p + 1, val, res);
        solve(p + 1, val + f[p], 1ll * res * f[p] % M);
         
    }
     
    int main() {
        f[0] = 1;
        f[1] = 1;
        for(int i = 2; i < 40; i++) {
            f[i] = f[i - 1] + f[i - 2];
        }
        mx = 23;
        dfs(0, 0, 1);
        solve(mx, 0, 1);
        int t;
        scanf("%d", &t);
        while(t--) {
            int n;
            scanf("%d", &n);
            printf("%d
    ", (ans[n] + ans2[n]) % M);
        }
    }
    

    方法二:
    Fibonacci数列前缀和为(g(n)=f(n+2)-1)。设小于等于n的最大的两个项为(f_{0n})(f_{1n}),那么n只能包含这两者中的一个。因此可以设(dp_{0n})(dp_{1n})为选择两者中一个的答案,这样直接dp可以计算。注意选择的冲突处理,详见代码。

    #include<iostream>
    using namespace std;
    const int N = 1e7 + 10;
    const int M = 998244353;
    typedef long long ll;
    
    int dp[2][N];
    int f[40];
    
    int main() {
    	f[0] = f[1] = 1;
    	dp[0][0] = 1;
    	dp[0][1] = 1;
    	dp[1][1] = 1;
    	for(int i = 2; i < 40; i++) f[i] = f[i - 1] + f[i - 2];
    	int cur = 0;
    	for(int i = 2; i < N; i++) {
    		if(i >= f[cur]) {
    			while(i >= f[cur]) cur++;
    			cur--;
    		}
    		int v1 = f[cur], v2 = f[cur - 1];
    		dp[0][i] = 1ll * (dp[0][i - v1] + dp[1][i - v1]) * v1 % M;
    		if(i - v2 < v2) // i-v2已经包含位置cur,故i不能选cur
    			dp[1][i] = 1ll * (dp[0][i - v2] + dp[1][i - v2]) * v2 % M;
    		else 
    			dp[1][i] = 1ll * (dp[1][i - v2]) * v2 % M;
    	}
    	int t;
    	scanf("%d", &t);
    	while(t--) {
    		int n;
    		scanf("%d", &n);
    		printf("%d
    ", (dp[0][n] + dp[1][n]) % M);
    	}
    }
    
  • 相关阅读:
    Eclipse安装Hadoop插件
    (转)Ubuntu14.0.4中hadoop2.4.0伪分布模式配置
    Hadoop--DataNode无法启动
    启动与关闭hadoop
    hadoop中执行命令时发生错误
    strings命令
    Deriving data from ElasticSearch Engine
    elasticsearch data importing
    reading words in your computer and changing to female voice, linux festival text2wave saving wav files
    DDNS client on a Linux machine
  • 原文地址:https://www.cnblogs.com/limil/p/14973631.html
Copyright © 2011-2022 走看看