题解

23 条题解

  • 2
    @ 2016-08-08 14:09:23
    #include <iostream>
    #include <cstring>
    #include <bitset>
    
    using namespace std;
    typedef long long lg;
    //#define OPENFILE
    #define ll lg
    
    lg f[2][1<<9][81],w=0;
    lg n,k,m;
    lg st[1<<9],sum[100],cnt=0,ans=0;
    int r[10000];
    
    inline int o(int n){return (n+1)&1;}
    
    inline lg gcd(lg a,lg b){return b==0?a:gcd(b,a%b);}
    
    void c(lg a,lg b)
    {
        lg res=1,k,re=1;
        for(int i=2;i<=a;i++)
            res*=i;
        for(int i=b;i>b-a;i--)
        {
            re*=i;
            k=gcd(re,res);
            res/=k;
            re/=k;
        }
        k=gcd(ans,re);
        ans/=k;
        re/=k;
        cout<<re<<"/"<<ans*res;
    }
    
    int main(int argc, char** argv)
    {
    #  ifdef OPENFILE
       freopen("data.in","r",stdin);
    #  endif
       ios::sync_with_stdio(0);
       cin>>n>>m>>k;
       if(n<m)
       {
          n=n^m;
          m=n^m;
          n=n^m;
       }
       int all=(1<<m)-1;
       for(int i=0;i<=all;i++)
        if(!(i&(i>>1)))
        {
            st[++cnt]=i;
            bitset<16>tt(i);
            sum[cnt]=tt.count();
            f[w][cnt][sum[cnt]]=1;
        }
       for(int i=2;i<=n;i++)
       { 
          w=o(w);
           memset(f[w],0,sizeof f[w]);
          for(int j=1;j<=cnt;j++)
            for(int c=1;c<=cnt;c++)
             if(!(st[j]&st[c])) 
             { 
               for(int t=0;t<=k-sum[j];t++)
                    f[w][j][t+sum[j]]+=f[o(w)][c][t];
             }
       }
       for(int i=1;i<=cnt;i++)
           ans+=f[w][i][k];
       if(ans)
          c(k,n*m);
       else
          cout<<"Impossible!";
       return 0;
    }
    
  • 1
    @ 2014-06-23 19:46:23

    最后在求组合数的时候数据很大……所以可以先求k!,然后在求n*m-k+1 到 n*m时不断用k!和答案去约它,这样就不会爆int64……

    • @ 2017-08-04 22:33:26

      用二阶递推式求组合数也不会爆

  • 1
    @ 2013-08-13 23:43:07

    #include<cstdio>
    using namespace std;
    const bool b[513]={true,true,true,false,true,true,false,false,true,true,true,false,false,false,false,false,true,true,true,false,true,true,false,false,false,false,false,false,false,false,false,false,true,true,true,false,true,true,false,false,true,true,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,true,true,false,true,true,false,false,true,true,true,false,false,false,false,false,true,true,true,false,true,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,true,true,false,true,true,false,false,true,true,true,false,false,false,false,false,true,true,true,false,true,true,false,false,false,false,false,false,false,false,false,false,true,true,true,false,true,true,false,false,true,true,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false};
    const int sl[513]={0,1,1,0,1,2,0,0,1,2,2,0,0,0,0,0,1,2,2,0,2,3,0,0,0,0,0,0,0,0,0,0,1,2,2,0,2,3,0,0,2,3,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2,2,0,2,3,0,0,2,3,3,0,0,0,0,0,2,3,3,0,3,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2,2,0,2,3,0,0,2,3,3,0,0,0,0,0,2,3,3,0,3,4,0,0,0,0,0,0,0,0,0,0,2,3,3,0,3,4,0,0,3,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
    double f[2][513][21];
    int n,m,k;
    double ccc(int x,int y)
    {
    double c=1,d=1;
    for(int i=1;i<=x;i++) c*=i;
    for(int i=y;i>=y-x+1;i--) d*=i;
    return d/c;
    }
    long long gcd(long long a,long long b)
    {
    if (b==0) return a;
    return gcd(b,a%b);
    }
    int main()
    {
    scanf("%d%d%d",&n,&m,&k);
    if (m>n)
    {
    int t=n;
    n=m;
    m=t;
    }
    double anss1=ccc(k,n*m);
    int ma=(1<<m)-1;
    for(int i=0;i<=ma;i++)
    if (b[i]&&sl[i]<=k)
    f[1][i][sl[i]]=1;
    for(int i=2;i<=n;i++)
    {
    for(int j=0;j<=ma;j++)
    for(int s=0;s<=k;s++)
    f[i%2][j][s]=0;
    for(int s=0;s<=k;s++)
    for(int j=0;j<=ma;j++)
    if (b[j]&&sl[j]<=s)
    for(int t=0;t<=ma;t++)
    if ((j&t)==0&&b[t]&&sl[t]<=(s-sl[j]))
    f[i%2][j][s]+=f[(i-1)%2][t][s-sl[j]];
    }
    double anss2=0;
    for(int i=0;i<=ma;i++)
    if (b[i])
    anss2+=f[n%2][i][k];
    if (anss2==0) printf("Impossible!");
    else
    {
    long long tt=gcd((long long)anss1,(long long)anss2);
    printf("%0.0lf/%0.0lf\n",anss1/tt,anss2/tt);
    }
    return 0;
    }

    最后一个点WA了求大神看看。。

    • @ 2017-08-09 10:43:05

      你的做法,。。。。厉害

  • 0
    @ 2017-11-09 14:16:20

    注意,求组合数的时候,用"C(n,m) = C(n,m-1) * (n-m+1) / m",就算是64位整数也会爆,用杨辉三角来递推就不会爆

  • 0
    @ 2017-07-19 11:03:27

  • 0
    @ 2017-07-19 10:43:50

    hehehheheheh

  • 0
    @ 2017-07-15 19:05:43

    可不可以用状压DP?

  • 0
    @ 2016-09-19 22:42:09

    此题简直叼………………
    ```C++
    #include <set>
    #include <map>
    #include <list>
    #include <cmath>
    #include <ctime>
    #include <deque>
    #include <queue>
    #include <stack>
    #include <cctype>
    #include <cstdio>
    #include <string>
    #include <vector>
    #include <cassert>
    #include <cstdlib>
    #include <cstring>
    #include <sstream>
    #include <iostream>
    #include <algorithm>
    #define maxn (1000 + 20)
    #define inf 0x3f3f3f3f
    #define pi acos(-1.0)
    using namespace std;
    typedef long long int LLI;

    int state[100],cnt = 0,counts[100];
    bool flag[100];
    int gts[15];
    int n,m,k;
    LLI dp[200][2000][25];

    void dfs(int last,int p,int c) {
    if(p >= m) {
    int s = 0;
    for(int i = 0; i < m; i ++) s = s * 2 + gts[i];
    counts[cnt] = c;
    state[cnt ++] = s;
    return;
    }
    if(p - last > 1) {
    gts[p] = 1;
    dfs(p,p + 1,c + 1);
    gts[p] = 0;
    dfs(last,p + 1,c);
    } else {
    gts[p] = 0;
    dfs(last, p + 1,c);
    }
    }

    LLI Com() {
    LLI re = 1;
    LLI x = n * m;
    LLI y = min(n * m - k,k);
    LLI z = max(n * m - k,k);
    LLI p = 2;
    for(int i = x; i >= z + 1; i --) {
    re = re * i;
    while(re % p == 0 && p <= y) {
    re = re / p;
    p ++;
    }
    }
    return re;
    }

    int main() {
    // freopen("in.txt","r",stdin);
    // freopen("out.txt","w",stdout);
    scanf("%d%d%d",&n,&m,&k);
    memset(flag,false,sizeof(flag));
    if(m > n) swap(n,m);
    dfs(-2,0,0);
    memset(dp,0,sizeof(dp));
    for(int j = 0; j < cnt; j ++) {
    dp[1][j][counts[j]] ++;
    }
    for(int i = 1; i <= n; i ++)
    for(int j = 0; j < cnt; j ++)
    for(int l = 0; l < cnt; l ++)
    if((state[j] & state[l]) == 0)
    for(int k1 = 0; k1 <= k; k1 ++)
    dp[(i + 1)][j][k1 + counts[j]] += dp[i][l][k1];
    LLI re = 0;
    for(int i = 0; i < cnt; i ++)
    re += dp[n][i][k];
    if(re == 0) printf("Impossible!\n");
    else {
    LLI p = Com();
    LLI GCD = __gcd(re,p);
    printf("%lld/%lld\n",p / GCD,re / GCD);
    }
    return 0;
    }
    ```

    • @ 2017-08-09 10:44:39

      可以用

      #include<bits/stdc++.h>
      
  • 0
    @ 2015-05-13 14:47:19

    #include<cstdio>
    #include<iostream>
    #define LL long long
    using namespace std;

    int vnum,n,m,k;
    LL ans;
    LL f[81][60][21],vis[60],c[60];

    void Swap(int &x,int &y){
    int t;
    t=x;
    x=y;
    y=t;
    }
    int Check(int x){
    int tot=0;
    for(int i=0;i<m;i++)
    if (x&(1<<i)) tot++;
    return tot;
    }
    void Getvalidstate(){
    for(int i=0;i<(1<<m);i++)
    if (!(i&(i<<1))){
    vis[++vnum]=i;
    c[vnum]=Check(i);
    }
    }
    LL Gcd(LL x,LL y){
    if (y==0) return x;
    else return Gcd(y,x%y);
    }
    /*void C(LL x,LL y){
    LL x1,x2,p;
    x1=1,x2=ans;
    for(int i=y;i>=1;i--){
    x1*=x;
    x2*=i;
    p=Gcd(x1,x2);
    x1/=p;
    x2/=p;
    x--;
    }
    cout<<x1<<'/'<<x2<<endl;
    }*/
    void C(LL x,LL y){
    LL x1,x2,p;
    x1=x2=1;
    for(int i=1;i<=y;i++)
    x2*=i;
    for(int i=1;i<=y;i++){
    x1*=x;
    p=Gcd(x1,x2);
    x1/=p;
    x2/=p;
    p=Gcd(x1,ans);
    x1/=p;
    ans/=p;
    x--;
    }
    x2*=ans;
    p=Gcd(x1,x2);
    x1/=p;
    x2/=p;
    cout<<x1<<'/'<<x2<<endl;
    }
    int main(){
    //freopen("p1.in","r",stdin);
    scanf("%d%d%d",&n,&m,&k);
    if (n<m) Swap(n,m);
    vnum=0;
    Getvalidstate();
    f[0][1][0]=1;
    for(int i=1;i<=n;i++)
    for(int j=1;j<=vnum;j++)
    for(int l=c[j];l<=k;l++)

    for(int h=1;h<=vnum;h++)
    if (!(vis[j]&vis[h])) f[i][j][l]+=f[i-1][h][l-c[j]];
    ans=0;
    for(int i=1;i<=vnum;i++)
    ans+=f[n][i][k];
    if (!ans) printf("Impossible!");
    else C(n*m,k);
    return 0;
    }

  • 0
    @ 2013-08-19 15:34:03

    longlong足矣,状压dp+dp求组合数+gcd。。。这题数据太水了暴力80分。状压dp的数组没加longlong导致wa了好几次。。。

    评测结果

    编译成功

    测试数据 #0: Accepted, time = 0 ms, mem = 6980 KiB, score = 10

    测试数据 #1: Accepted, time = 0 ms, mem = 6980 KiB, score = 10

    测试数据 #2: Accepted, time = 0 ms, mem = 6988 KiB, score = 10

    测试数据 #3: Accepted, time = 15 ms, mem = 6984 KiB, score = 10

    测试数据 #4: Accepted, time = 0 ms, mem = 6988 KiB, score = 10

    测试数据 #5: Accepted, time = 0 ms, mem = 6988 KiB, score = 10

    测试数据 #6: Accepted, time = 0 ms, mem = 6980 KiB, score = 10

    测试数据 #7: Accepted, time = 15 ms, mem = 6988 KiB, score = 10

    测试数据 #8: Accepted, time = 0 ms, mem = 6980 KiB, score = 10

    测试数据 #9: Accepted, time = 0 ms, mem = 6980 KiB, score = 10

    Accepted, time = 30 ms, mem = 6988 KiB, score = 100

  • 0
    @ 2012-08-25 22:18:17

    压位DP,不用高精

  • 0
    @ 2008-07-17 13:52:03

    20分钟搞定~~

    在算总数的时候用extended

    然后加个0.5再取整

    为这个浪费了3次提交...

  • 0
    @ 2007-04-16 13:39:53

    瞎扯……int64显然够

  • 0
    @ 2006-11-06 09:31:33

    0,1来存储状态 DP

    详见"炮兵阵地"!

  • 0
    @ 2006-11-05 14:30:38

    原来取整用round和trunc支持的范围不同的,过大的实数用round会有216错误……

    为了这东西从早上弄到下午,换成trunc就AC

  • 0
    @ 2006-11-05 10:15:42

    先判断n*m 的奇偶,

    判断是否有解。



    加全排序...硬上...

    暴力拿了80分 2个点超时。。

    测试数据太弱了

  • 0
    @ 2006-11-05 08:02:12

    写了个不剪枝硬上的得了80 hoho

  • -2
    @ 2008-11-04 08:11:22

    我讲一点技巧,就是若n

  • -2
    @ 2006-11-10 20:28:18

    int64不够 用extended 我提交了5次

  • -2
    @ 2006-11-06 13:46:57

    汗啊。。。交了N次~

信息

ID
1286
难度
6
分类
动态规划 | 状态压缩DP数论 | 欧几里得算法 点击显示
标签
(无)
递交数
592
已通过
149
通过率
25%
被复制
8
上传者