HDU 4321 Arcane Numbers 2

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4321

-------------------------------------------------------------------------------

虽然有更优美的做法 不过数据范围还是可以数位$DP$的

即把模型转化为 在区间内 $mod\ a  = b\ mod\ a$ 的数所含$1$的个数之和

四维的数组分别记录 枚举到第$x$位 是否达到上限 $mod\ a$ 的余数 当前位是否为$1$ 这些状态

然后统计在这些状态下的数的个数$F$ 以及在这些状态下的数的总贡献 $G$

转移的话 $F$比较简单

$G$的话先把当前位之后的$G$全部转移上去 再把当前位根据$F$的大小算好贡献

之后就是一个记忆化搜索了

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cmath>
 4 #include <algorithm>
 5 using namespace std;
 6 long long f[50][2][10010][2], g[50][2][10010][2], two[50];
 7 int ti[50][2][10010][2];
 8 bool num[50];
 9 long long a, b, n, ans;
10 int t, len, tt;
11 void work(long long x)
12 {
13     memset(num, 0, sizeof num);
14     len = 0;
15     while(x)
16     {
17         num[++len] = x & 1;
18         x >>= 1;
19     }
20     two[0] = 1 % a;
21     for(int i = 1; i < len; ++i)
22         two[i] = two[i - 1] * 2 % a;
23 }
24 long long dfs(int x, bool top, int r, bool one)
25 {
26     if(ti[x][top][r][one] == tt)
27         return f[x][top][r][one];
28     ti[x][top][r][one] = tt;
29     if(x == 0)
30     {
31         g[x][top][r][one] = (one && (r == b % a));
32         return f[x][top][r][one] = (r == b % a);
33     }
34     f[x][top][r][one] = g[x][top][r][one] = 0;
35     if(top)
36     {
37         if(num[x])
38         {
39             f[x][top][r][one] += dfs(x - 1, 1, (two[x - 1] + r) % a, 1);
40             g[x][top][r][one] += g[x - 1][1][(two[x - 1] + r) % a][1];
41             f[x][top][r][one] += dfs(x - 1, 0, r, 0);
42             g[x][top][r][one] += g[x - 1][0][r][0];
43         }
44         else
45         {
46             f[x][top][r][one] += dfs(x - 1, 1, r, 0);
47             g[x][top][r][one] += g[x - 1][1][r][0];
48         }
49     }
50     else
51     {
52         f[x][top][r][one] += dfs(x - 1, 0, (two[x - 1] + r) % a, 1);
53         g[x][top][r][one] += g[x - 1][0][(two[x - 1] + r) % a][1];
54         f[x][top][r][one] += dfs(x - 1, 0, r, 0);
55         g[x][top][r][one] += g[x - 1][0][r][0];
56     }
57     g[x][top][r][one] += one * f[x][top][r][one];
58     return f[x][top][r][one];
59 }
60 int main()
61 {
62     scanf("%d", &t);
63     for(int ca = 1; ca <= t; ++ca)
64     {
65         scanf("%lld%lld%lld", &a, &b, &n);
66         work(b);
67         ++tt;
68         dfs(len + 1, 1, 0, 0);
69         ans = -g[len + 1][1][0][0];
70         work(b + n * a);
71         ++tt;
72         dfs(len + 1, 1, 0, 0);
73         ans += g[len + 1][1][0][0];
74         printf("Case #%d: %lld\n", ca, ans);
75     }
76     return 0;
77 }
时间: 2024-10-25 04:13:45

HDU 4321 Arcane Numbers 2的相关文章

HDU 4320 Arcane Numbers 1 (质因子分解)

题目:传送门. 题意:将一个A进制下的有限小数转化为B进制看是否仍为有限小数. 题解:一个A进制的小数可以下次 左移动n位变成A进制整数然后再将其转化为B进制即可 即B^m/A^n要整除,因此A的质因子B必须得全部含有. #include <iostream> #include <math.h> #include <string.h> #include <algorithm> #include <stdio.h> #include <std

2012 #3 Arcane Numbers

Arcane Numbers 1 Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit Status Practice HDU 4320 Description Vance and Shackler like playing games. One day, they are playing a game called "arcane numbers". The ga

hdu 3117 Fibonacci Numbers

点击此处即可传送到hdu 3117 **Fibonacci Numbers** Problem Description The Fibonacci sequence is the sequence of numbers such that every element is equal to the sum of the two previous elements, except for the first two elements f0 and f1 which are respectively

hdu 4722 Good Numbers(dp)

public static void main(String[] args) { String a=null; if("aa".equals(a))//这种情形,不出现空指针异常 //if(a.equals("aa"))//出现空指针异常 { System.out.println(true); } else { System.out.println(false); } } 上面的两句不同的比较语句测试,第一句不出现空指针异常,第二句出现. 所以在变量和常量比较的时候

HDU 3117 Fibonacci Numbers(斐波那契前后四位,打表+取对+矩阵快速幂)

HDU 3117 Fibonacci Numbers(斐波那契前后四位,打表+取对+矩阵快速幂) ACM 题目地址:HDU 3117 Fibonacci Numbers 题意: 求第n个斐波那契数的前四位和后四位. 不足8位直接输出. 分析: 前四位有另外一题HDU 1568,用取对的方法来做的. 后四位可以用矩阵快速幂,MOD设成10000就行了. 代码: /* * Author: illuz <iilluzen[at]gmail.com> * Blog: http://blog.csdn.

HDU 1058 Humble Numbers (dp+打表)

先是想筛法素数表啊,然后1~2000000000枚举打表啊,结果越想越不对. 后来想到唯一分解定理,可是怎么实现呢..果然还是需要努力啊.. 研究了discuss代码,码之~ ~~~~ dp的思想,若dp[i]是Humble Numbers,那么dp[i]*2,dp[i]*3,dp[i]*5,dp[i]*7都将是Humble Numbers. 所以只需要注意连续性便好了. #include<cstdio> #include<algorithm> #include<cmath&

HDU 4325 Vampire Numbers 打表

杭电服务器是慢啊.. #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <math.h> #include <set> #include <vector> #include <map> using namespace std; #define ll long long #define N

HDU 1058 Humble Numbers (打表)

题目链接:HDU 1058 Humble Numbers 题意:一些数他们的素数因子只有2,3,5,7.求这些数. 因为这些数的因子只可能是2,3,5,7.所以通过2,3,5,7这个四个数构造这个数列,这个数列靠后的数必定是前面的数乘上2,3,5,7得到. AC代码: #include<stdio.h> #include<set> #define ll __int64 using namespace std; set<ll> s; set<ll>::iter

hdu 4722 Good Numbers(初涉数位dp)

http://acm.hdu.edu.cn/showproblem.php?pid=4722 大致题意:若一个整数的各位数字之和是10的倍数,称这个数为"good number".给出区间[A,B],求出该区间内"good number"的数的个数. 第一道数位dp,折腾了半天才明白怎么回事. 设dp[site][mod]表示到第site位(由高位向低位)前面各位数字之和对10取余为mod的数的个数,进行记忆化搜索.有两个很重要的点,首先是变量up,表示是否到达边界