HDOJ5657 CA Loves Math

Posted Bombe

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDOJ5657 CA Loves Math相关的知识,希望对你有一定的参考价值。

1. 题目描述
对于给定的$a, n, mod, a \in [2,11], n \in [0, 10^9], mod \in [1, 10^9]$求出在$[1, a^n]$内的所有$a$进制下的数并且不含重复数字。

2. 基本思路
这题比赛的时候,没人做出来,但是基本思路大家都有。显然可以直接将$n$改写为$\min(n,a)$。
我比赛的代码TLE,思路是这样的:首先$mod$很小时,可以数位DP解;当$mod$很大时,可以先找到所有的排列然后,然后令$delta = fact(a)/fact(a-n)$,然后以这个作为循环间隔找到满足不重复的数字,然后再判断是否是$mod$的倍数。
hack的时候,其实可以直接以$mod$作为阈值解。题解也提到了这个思路。
这样原问题可以分两种情况:
(1) 大于阈值,枚举$mod$的倍数,然后判断是否包含重复数字;
(2) 小于等于阈值,数位DP。
然后,赛后交还是wa了几次。这里有几个特殊情况需要单独考虑:
(1) n = 0时,只能取1,直接判断是否为$mod$倍数。
(2) n = 1时,可以取[1, a],同样需要判断是否为$mod$倍数。
并且,数位DP是累加DP的。即长度为$[1,n]$的满足条件的总和。

3. 代码

  1 /*  */
  2 #include <iostream>
  3 #include <sstream>
  4 #include <string>
  5 #include <map>
  6 #include <queue>
  7 #include <set>
  8 #include <stack>
  9 #include <vector>
 10 #include <deque>
 11 #include <bitset>
 12 #include <algorithm>
 13 #include <cstdio>
 14 #include <cmath>
 15 #include <ctime>
 16 #include <cstring>
 17 #include <climits>
 18 #include <cctype>
 19 #include <cassert>
 20 #include <functional>
 21 #include <iterator>
 22 #include <iomanip>
 23 using namespace std;
 24 //#pragma comment(linker,"/STACK:102400000,1024000")
 25 
 26 #define sti                set<int>
 27 #define stpii            set<pair<int, int> >
 28 #define mpii            map<int,int>
 29 #define vi                vector<int>
 30 #define pii                pair<int,int>
 31 #define vpii            vector<pair<int,int> >
 32 #define rep(i, a, n)     for (int i=a;i<n;++i)
 33 #define per(i, a, n)     for (int i=n-1;i>=a;--i)
 34 #define clr                clear
 35 #define pb                 push_back
 36 #define mp                 make_pair
 37 #define fir                first
 38 #define sec                second
 39 #define all(x)             (x).begin(),(x).end()
 40 #define SZ(x)             ((int)(x).size())
 41 #define lson            l, mid, rt<<1
 42 #define rson            mid+1, r, rt<<1|1
 43 #define INF                0x3f3f3f3f
 44 #define mset(a, val)    memset(a, (val), sizeof(a))
 45 
 46 #define LL __int64
 47 
 48 const int bound = 23333;
 49 const int maxn = 12;
 50 int dp[1<<11][bound];
 51 int Bits[1<<11];
 52 vector<int> St[maxn];
 53 int Sz[maxn];
 54 int a, n, mod;
 55 
 56 void solve();
 57 void _solve();
 58 
 59 inline int lowest(int x) {
 60     return -x & x;
 61 }
 62 
 63 inline int getBits(int x) {
 64     int ret = 0;
 65     
 66     while (x) {
 67         ++ret;
 68         x -= lowest(x);
 69     }
 70     return ret;
 71 }
 72 
 73 void init() {
 74     int mst = 1 << 11;
 75     
 76     rep(i, 0, mst) {
 77         Bits[i] = getBits(i);
 78         St[Bits[i]].pb(i);
 79     }
 80     
 81     rep(i, 0, maxn)
 82         Sz[i] = SZ(St[i]);
 83 }
 84 
 85 bool vis[12];
 86 inline bool judge(LL x) {
 87     if (x == 0)    return false;
 88     
 89     memset(vis, false, sizeof(vis));
 90     while (x) {
 91         int tmp = x % a;
 92         if (vis[tmp])
 93             return false;
 94         x /= a;
 95         vis[tmp] = true;
 96     }
 97     return true;
 98 }
 99 
100 void solve() {
101     if (n == 0) {
102         printf("%d\n", 1%mod==0 ? 1:0);
103         return ;
104     }
105     if (n == 1) {
106         int ans = 0;
107         rep(i, 1, a+1)
108             ans += i%mod == 0 ? 1:0;
109         printf("%d\n", ans);
110         return ;
111     }
112     
113     n = min(n, a);
114     if (mod > bound) {
115         _solve();
116         return ;
117     }
118 
119     int mst = 1<<a;
120     memset(dp, 0, sizeof(dp));
121     
122     rep(j, 1, a)
123         ++dp[1<<j][j%mod];
124     
125     rep(l, 1, n) {
126         rep(j, 0, Sz[l]) {
127             const int st = St[l][j];
128             if (st >= mst)
129                 continue;
130             rep(k, 0, mod) {
131                 const int& cnt = dp[st][k];
132                 if (cnt == 0)
133                     continue;
134                 
135                 rep(i, 0, a) {
136                     if (st & (1<<i))
137                         continue;
138                     
139                     int nst = st | (1<<i);
140                     int nk = (k * a + i) % mod;
141                     dp[nst][nk] += cnt;
142                 }
143             }
144         }
145     }
146     
147     int ans = 0;
148     
149     rep(l, 1, n+1) {
150         rep(j, 0, Sz[l]) {
151             const int& st = St[l][j];
152             ans += dp[st][0];
153         }
154     }
155     
156     printf("%d\n", ans);
157 }
158 
159 LL Pow(LL base, int n) {
160     LL ret = 1;
161     
162     while (n) {
163         if (n & 1)
164             ret = ret * base;
165         base = base * base;
166         n >>= 1;
167     }
168     
169     return ret;
170 }
171 
172 void _solve() {
173     LL tmp = mod, ubound = Pow(a, n);
174     int ans = 0;
175     
176     while (tmp <= ubound) {
177         if (judge(tmp))
178             ++ans;
179         tmp += mod;
180     }
181     
182     printf("%d\n", ans);
183 }
184 
185 int main() {
186     ios::sync_with_stdio(false);
187     #ifndef ONLINE_JUDGE
188         freopen("data.in", "r", stdin);
189         freopen("data.out", "w", stdout);
190     #endif
191 
192     int t;
193 
194     init();
195     scanf("%d", &t);
196     while (t--) {
197         scanf("%d%d%d",&a,&n,&mod);
198         solve();
199     }
200 
201     #ifndef ONLINE_JUDGE
202         printf("time = %ldms.\n", clock());
203     #endif
204 
205     return 0;
206 }

 

以上是关于HDOJ5657 CA Loves Math的主要内容,如果未能解决你的问题,请参考以下文章

HDOJ7079Pty loves lines(计算直线的交点方案数,打表)

HDOJ6986Kanade Loves Maze Designing(暴力,dfs树)

hdu 5656 CA Loves GCD

bzoj 3309 DZY Loves Math —— 莫比乌斯反演+数论分块

hdu 5655 CA Loves Stick

hdu-5655 CA Loves Stick(水题)