lightoj1021- Painful Bases

题目链接:http://lightoj.com/volume_showproblem.php?problem=1021

求一个base进制下的合法数字s的组合当中能够整除k的个数。

开始是暴利去做的,以为枚举后面几个数就好了,前面的只需要排列数,结果wa了,其实最要是这个本身我也觉得存在问题,所以就没在纠结,只是碰运气的。

然后,base <= 16,k <= 20,且题目有说道有效数字的长度小于16,所以可以用状压。

dp[i][j],i是状态,j是这个状态的数模k的余数,然后转移就是某个有效状态添加某个数后其可达的另一个状态。

感悟:还是题写少了,一开始就没有往dp上想。此题还是基础的。

/*****************************************
Author      :Crazy_AC(JamesQi)
Time        :2015
File Name   :
*****************************************/
// #pragma comment(linker, "/STACK:1024000000,1024000000")
#include <iostream>
#include <algorithm>
#include <iomanip>
#include <sstream>
#include <string>
#include <stack>
#include <queue>
#include <deque>
#include <vector>
#include <map>
#include <set>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <climits>
using namespace std;
#define MEM(x,y) memset(x, y,sizeof x)
#define pk push_back
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> ii;
const double eps = 1e-10;
const int inf = 1 << 30;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
LL dp[1 << 17][20];
char s[40];
int trans(char c){
    if (c >= '0' && c <= '9') return c - '0';
    return c - 'A' + 10;
}
int main()
{    
    // freopen("in.txt","r",stdin);
    // freopen("out.txt","w",stdout);
    int t, icase = 0;
    cin >> t;
    while(t--){
        int base,k;
        cin >> base >> k;
        cin >> s;
        int len = strlen(s);
        memset(dp, 0,sizeof dp);
        dp[0][0] = 1;
        for (int i = 0;i < (1 << len);++i){
            for (int j = 0;j < len;++j){
                if (i & (1 << j)) continue;
                for (int r = 0;r < k;++r){
                    if (!dp[i][r]) continue;
                    dp[i | (1 << j)][(r * base + trans(s[j])) % k] += dp[i][r];
                }
            }
        }
        cout << "Case " << ++icase << ": ";
        cout << dp[(1 << len) - 1][0] << endl;
    }
    return 0;
}


你可能感兴趣的:(dp,lightoj)