• Painful Bases LightOJ


    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
    ",TT,get(tt,0));
    56     }
    57     return 0;
    58 }
  • 相关阅读:
    关于MAC下重置MYSQL密码
    MAC下配置PHPStorm环境
    Java中从控制台输入数据的几种常用方法
    IDEA 指定入口class
    Python中的除法
    Python 学习笔记
    SQLiteDatabase中query、insert、update、delete方法参数说明
    listview与sqlite数据绑定
    java中HashMap详解
    只要有信心,人永远不会挫败
  • 原文地址:https://www.cnblogs.com/hehe54321/p/loj-1021.html
Copyright © 2020-2023  润新知