Painful Bases LightOJ - 1021

Painful Bases LightOJ - 1021

题意:给出0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F中的一些字符(不重复)还有一个进制base,求这些字符的排列形成的base进制数中,有多少个能被k整除。

方法:

正常的做法:

http://blog.csdn.net/chenzhenyu123456/article/details/51155038

自己的做法(常数很大,仅做记录):

ans[i][S][j]表示i进制下,S集合中数字可用,总产生余数为j时方案数

digit(S)表示S集合中元素数量。那么,当前数字为一个digit(S)位的base进制数,其第digit(S)位的值转换为10进制后除以k产生的余数就是j。

ans[i][S][j]=sum{ans[i][S-p][(j+k-pow(i,digit(S)-1)*p%k)%k}

其含义:把S中任意一个数字p当做首位,首位产生的余数$pow(i,digit(S)-1)*p%k$,然后剩下数字的余数应该是$(j+k-pow(i,digit(S)-1)*p%k)%k$。

实际使用时,这样定义状态会爆空间,因此只能把i的一维舍去,每组数据都重新算。

错误次数:2

原因:

1.用循环,被卡常,改成了记忆化搜索。

2.在用循环的时候,为了卡常,改了循环内外层,但不正确。

卡常记录:把记录a^b改成记录所有a^b%k,时间缩短到1/3。

 1 #include<cstdio>
 2 #include<cstring>
 3 typedef long long LL;
 4 LL ans[70000][22];
 5 LL T,TT;
 6 bool ok[20];
 7 char ss[20];
 8 LL popcount[70000];
 9 LL powww[30][30][30];
10 LL base,k;
11 LL poww(LL a,LL b)
12 {
13     if(powww[a][b][k])    return powww[a][b][k];
14     LL base=a,ans=1,b1=b;
15     while(b)
16     {
17         if(b&1)    ans=ans*base%k;
18         b>>=1;
19         base=base*base%k;
20     }
21     return powww[a][b1][k]=ans;
22 }
23 LL get(LL s,LL j)
24 {
25     if(ans[s][j]!=-1)    return ans[s][j];
26     int j1;
27     ans[s][j]=0;
28     for(j1=0;j1<base;j1++)
29         if(s&(1<<j1))
30             ans[s][j]+=get(s^(1<<j1),(j+k-poww(base,__builtin_popcount(s)-1)*j1%k)%k);
31     return ans[s][j];
32 }
33 int main()
34 {
35     LL i,tt;
36     for(i=1;i<(1<<16);i++)
37         popcount[i]=__builtin_popcountll(i);
38     scanf("%lld",&T);
39     for(TT=1;TT<=T;TT++)
40     {
41         tt=0;
42         memset(ok,0,sizeof(ok));
43         memset(ans,-1,sizeof(ans));
44         scanf("%lld%lld",&base,&k);
45         ans[0][0]=1;
46         scanf("%s",ss);
47         for(i=0;i<strlen(ss);i++)
48             if(ss[i]>='0'&&ss[i]<='9')
49                 ok[ss[i]-'0']=1;
50             else
51                 ok[ss[i]-'A'+10]=1;
52         for(i=0;i<base;i++)
53             if(ok[i])
54                 tt^=(1<<i);
55         printf("Case %lld: %lld\n",TT,get(tt,0));
56     }
57     return 0;
58 }
posted @ 2017-10-28 13:42  hehe_54321  阅读(188)  评论(0编辑  收藏  举报
AmazingCounters.com