zoukankan      html  css  js  c++  java
  • 【LOJ6089】小Y的背包计数问题(动态规划)

    【LOJ6089】小Y的背包计数问题(动态规划)

    题面

    LOJ

    题解

    神仙题啊。
    我们分开考虑不同的物品,按照编号与(sqrt n)的关系分类。
    第一类:(ile sqrt n)
    即需要考虑所有的情况,那么设(f[i][j])表示前(i)个物品装了体积(j)的方案数。
    显然(f[i][j]=sum_{k=1}^i f[i][j-k*i])转移过来,那么按照(i)分剩余类,前缀和转移即可。
    这一部分的复杂度是(O(nsqrt n))
    第二类:(ige sqrt n)
    因为(i*ige n),所以这一部分的任何一个物品都不存在个数的限制,即可以随意选择。
    那么我们只需要用所有大于(sqrt n)的数做整数划分就行了。
    (g[i][j])表示当前一共划分出来了(i)个数,和为(j)的方案数,每次要么加入一个(sqrt n),要么把所有数(+1)
    这一部分因为数的共个数,即(i)不会超过(sqrt n),所以总的复杂度也是(O(nsqrt n))的。
    那么这题的总复杂度就是(O(nsqrt n))了。

    #include<iostream>
    #include<cstring>
    #include<cmath>
    using namespace std;
    #define ll long long
    #define MOD 23333333
    #define MAX 100100
    int n,m,ans;
    int f[350][MAX],g[350][MAX],s[MAX];
    int main()
    {
    	cin>>n;m=sqrt(n);
    	f[0][0]=1;
    	for(int i=1;i<=m;++i)
    	{
    		for(int j=0;j<i;++j)
    		{
    			int tot=0;
    			for(int k=j;k<=n;k+=i)s[++tot]=f[i-1][k];
    			for(int k=1;k<=tot;++k)s[k]=(s[k-1]+s[k])%MOD;
    			for(int k=j,tot=0;k<=n;k+=i,++tot)
    				f[i][k]=(f[i][k]+s[tot+1]-s[max(0,tot-i)]+MOD)%MOD;
    		}		
    	}
    	memset(s,0,sizeof(s));g[0][0]=s[0]=1;
    	for(int i=1;i<=m;++i)
    		for(int j=0;j<=n;++j)
    		{
    			if(j>=i)g[i][j]=(g[i][j]+g[i][j-i])%MOD;
    			if(j>=m+1)g[i][j]=(g[i][j]+g[i-1][j-(m+1)])%MOD;
    			s[j]=(s[j]+g[i][j])%MOD;
    		}
    	for(int i=0;i<=n;++i)ans=(ans+1ll*s[n-i]*f[m][i])%MOD;
    	printf("%d
    ",ans);
    	return 0;
    }
    
    
  • 相关阅读:
    Web应用网络模型
    Http协议
    Array数组标准库
    Array数组基础
    javascript--Object
    javascript--Function
    letCode-3
    面试前的准备
    面试常见问题
    面试经验总结
  • 原文地址:https://www.cnblogs.com/cjyyb/p/9669418.html
Copyright © 2011-2022 走看看