zoukankan      html  css  js  c++  java
  • 【奇妙dp】ARC107D Number of Multisets

    题目链接

    题目解析

    我是这么想的:

    (1=frac{1}{2^i}*2^i)

    所以题目是求(k)个形如(2^i)的形式的数的和为(n)的方案数。(然而并没有什么用,只是把题意反过来了而已qwq

    (忘掉前面的东西

    考虑这样一个(dp):设(f[i][j])表示(i)个数和为(j),考虑转移,由于放数的种类繁多难以统计,我们把放数看成是两种操作:

    一个是往集合里放一个(1),另一个是把集合里的所有数全部除以(2),容易发现,这两种操作可以包含所有放数的集合。(这个转化非常奇妙)

    转移就比较明晰了:(f[i][j]=f[i-1][j-1]+f[i][2*j])

    注意这个转移的顺序应该是外层(i)从小到大,内层(j)从大到小。


    ►Code View

    #include<cstdio>
    #include<algorithm>
    #include<iostream>
    #include<vector>
    #include<queue>
    #include<cstring>
    #include<ctime>
    #include<map>
    using namespace std;
    #define N 3005
    #define LL long long
    #define INF 0x3f3f3f3f
    #define MOD 998244353
    int rd()
    {
    	int x=0,f=1;char c=getchar();
    	while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();}
    	while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+(c^48); c=getchar();}
    	return f*x;
    }
    int n,k;
    LL f[N][N]; 
    int main()
    {
    	n=rd(),k=rd();
    	f[0][0]=1;
    	for(int i=1;i<=n;i++)
    		for(int j=i;j>=1;j--)//i个数 和最大是i
    			f[i][j]=(f[i-1][j-1]+f[i][j<<1])%MOD;
    	printf("%lld
    ",f[n][k]);
        return 0;
    }
    
    
  • 相关阅读:
    C语言寒假大作战01
    C语言I作业12—学期总结
    C语言I博客作业11
    C语言I博客作业10
    非数值数据的编码方式
    定点数
    C语言||作业01
    C语言寒假大作战04
    C语言寒假大作战03
    C语言寒假大作战02
  • 原文地址:https://www.cnblogs.com/lyttt/p/13932975.html
Copyright © 2011-2022 走看看