首页 > 其他 > 详细

【LG4317】花神的数论题

时间:2019-01-05 18:04:55      阅读:149      评论:0      收藏:0      [点我收藏+]

【LG4317】花神的数论题

题面

洛谷

题解

\(f_{i,up,tmp,d}\)表示当前在第\(i\)位,是否卡上界,有\(tmp\)个一,目标是几个一的方案数
最后将所有\(d\)固定,套数位\(dp\)的板子
然后快速幂乘起来就好了
代码

#include <iostream> 
#include <cstdio>
#include <cstdlib>
#include <cstring> 
#include <cmath> 
#include <algorithm>
#include <vector> 
using namespace std;
#define int long long 
const int Mod = 1e7 + 7; 
int N, f[55][2][55][55];
vector<int> digit;
int fpow(int x, int y) {
    int res = 1;
    while (y) {
        if (y & 1) res = 1ll * res * x % Mod; 
        x = 1ll * x * x % Mod;
        y >>= 1ll; 
    }
    return res; 
} 
int dfs(int o, bool up, int tmp, int d) { 
    if (o == -1) return tmp == d; 
    if (~f[o][up][tmp][d]) return f[o][up][tmp][d]; 
    int lim = up ? digit[o] : 1, res = 0; 
    for (int i = 0; i <= lim; i++) res = res + dfs(o - 1, up && i == lim, tmp + (i == 1), d); 
    return f[o][up][tmp][d] = res; 
}
int ans[100]; 
int solve(int n) { 
    while (n) digit.push_back(n & 1ll), n >>= 1ll;
    digit.push_back(0); 
    for (int i = 1; i <= 50; i++) {
        memset(f, -1, sizeof(f)); 
        ans[i] = dfs(digit.size() - 1, 1, 0, i); 
    } 
    int res = 1;
    for (int i = 1; i <= 50; i++) res = 1ll * res * fpow(i, ans[i]) % Mod;
    return res; 
} 
signed main () {
    cin >> N; 
    printf("%lld\n", solve(N)); 
    return 0; 
} 

【LG4317】花神的数论题

原文:https://www.cnblogs.com/heyujun/p/10225228.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!