zoukankan      html  css  js  c++  java
  • [hihocoder1259] A Math Problem (数学,数位dp)

    题目链接:http://hihocoder.com/problemset/problem/1259

    式子可以化简,并且找到一个f的递推式,递推过程如下:

    列出来后手动枚举几个f的值,会发现函数值其实就是把二进制的自变量当成三进制来算一次。

    答案求的是异或和,要求将所有余数相同的和异或起来,可以考虑用数位dp了,f(i,j)表示长为i的时候,余数为j。由于从高到低更新,那么f(i,j)=∑f(i-1, j+3^(i-1)*(k==1)),k取值为0或者1。倒着推可以一直用期望的余数减去当前加上某位值后的余数,判断最后到头的时候余数是不是0。

    这么交是会TLE的,原因是每次都要clear dp数组。

    由于只有5个模数,不放再多加一维,记录各个模下的不同余数个数和。

    再预处理一下不同模下的幂取模值就行了。

    特别注意下:f(0)不存在,但是dp出来f(0)=0,%k=0,所以在处理的时候要减掉这个值。

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 
     4 typedef long long LL;
     5 const int maxn = 66;
     6 const int maxm = 66666;
     7 const int mod[5] = {3,5,17,257,65537};
     8 LL n;
     9 int k, id;
    10 LL dp[6][maxn][maxm];
    11 int mul[6][maxn];
    12 int digit[maxn];
    13 
    14 LL dfs(int l, int sum, bool flag) {
    15     if(l == 0) return sum == 0;
    16     if(!flag && ~dp[id][l][sum]) return dp[id][l][sum];
    17     int pos = flag ? digit[l] : 1;
    18     LL ret = 0;
    19     for(int i = 0; i <= pos; i++) {
    20         if(i == 0) ret += dfs(l-1, sum, flag&&(i==pos));
    21         else ret += dfs(l-1, (sum+k-mul[id][l-1])%k, flag&&(i==pos));
    22     }
    23     if(!flag) dp[id][l][sum] = ret;
    24     return ret;
    25 }
    26 
    27 LL f(LL n, int sum) {
    28     int pos = 0;
    29     while(n) {
    30         digit[++pos] = n % 2;
    31         n >>= 1;
    32     }
    33     return dfs(pos, sum, true);
    34 }
    35 
    36 int main() {
    37     // freopen("in", "r", stdin);
    38     int T;
    39     scanf("%d", &T);
    40     for(int i = 0; i < 5; i++) {
    41         mul[i][0] = 1;
    42         for(int j = 1; j < maxn; j++) {
    43             mul[i][j] = (mul[i][j-1] * 3) % mod[i];
    44         }
    45     }
    46     memset(dp, -1, sizeof(dp));
    47     while(~scanf("%lld%d",&n,&k)) {
    48         id = lower_bound(mod, mod+5, k) - mod;
    49         LL ret = 0;
    50         for(int i = 0; i < k; i++) ret ^= (f(n, i) - (i == 0));
    51         printf("%lld
    ", ret);
    52     }
    53     return 0;
    54 }
  • 相关阅读:
    android studio首次运行出错
    分享4种CSS3效果(360度旋转、旋转放大、放大、移动)
    重温CSS:Border属性
    CSS3之过渡Transition
    ASP.NET(C#)--Repeater中生成“序号”列
    Android开发过程问题集锦(Continuous updating)
    ZOJ Problem Set Vol 1(Update paste)
    MapReduce基本原理及应用
    Tensorflow之基于MNIST手写识别的入门介绍[转载]
    Tensorflow 计算模型——计算图
  • 原文地址:https://www.cnblogs.com/kirai/p/6824812.html
Copyright © 2011-2022 走看看