T 1 : P 6065 \tt T1:P6065 T1:P6065
将每个
2
2
2 的幂视为物品的重量
w
i
w_i
wi,容量为
n
n
n,物品的个数需要统计幂的数量
p
o
s
pos
pos,然后是完全背包求方案数。
注意:因为要求取模,推荐一个公式
(
a
+
b
)
m
o
d
c
(a+b)\mod c
(a+b)modc 相当于
(
(
a
m
o
d
c
)
+
(
b
m
o
d
c
)
)
m
o
d
c
((a\mod c)+(b\mod c))\mod c
((amodc)+(bmodc))modc
代码:
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int mod=1e9;
int n,dp[1000005],w[105],cnt=1,pos;
signed main()
{
cin>>n;
dp[0]=1;
w[0]=cnt;
while(cnt<=n)
{
cnt*=2;
w[++pos]=cnt;
}
for(int i=0;i<pos;i++)
{
for(int j=w[i];j<=n;j++)
{
dp[j]=(dp[j]%mod+dp[j-w[i]]%mod)%mod;
}
}
cout<<dp[n]%mod;
return 0;
}
T 2 : P 1466 \tt T2:P1466 T2:P1466
先判断累加的奇偶性,如果是奇数直接结束程序。
而是偶数的数,对于只选前
i
i
i 项的数,它们的和正好是
j
j
j 的方案总数。
答案:第
i
i
i 个数选不选,所以由此得出方案总数就应该是选的方案和不选的方案之和。
注意等差数列求和公式:
(
a
+
b
)
⋅
n
2
\frac{(a+b)\cdot n}{2}
2(a+b)⋅n
代码:
#include<bits/stdc++.h>
using namespace std;
#define int long long
int n,dp[2000],w[45];
signed main()
{
cin>>n;
dp[0]=1;
if(n*(n+1)/2%2==1)
{
cout<<0;
return 0;
}
for(int i=1;i<=n;i++)
{
w[i]=i;
}
for(int i=1;i<=n;i++)
{
for(int j=n*(n+1)/2;j>=w[i];j--)
{
dp[j]+=dp[j-w[i]];
}
}
cout<<dp[n*(n+1)/4]/2;
return 0;
}
T 3 : P 2392 \tt T3:P2392 T3:P2392
首先,我没需要证明一点: 4 4 4 个学科独立刷题,是做 4 4 4 遍背包,不要被那个左右大脑误解了。
其次,做一个科目的时间不会超过所有题目时间的总和。
接下来,有几点:
- 如果要是花费的总时间小,那么左右半脑的处理题目的时间就要尽可能地相似,一个不大于 t 2 \frac{t}{2} 2t,一个不小于 t 2 \frac{t}{2} 2t。
- 我们这里先将用时较短的半脑作为目标,让他尽量多。
最后是对应关系:
- 容量:时间
- 物品:题目
- 重量与价值:每道题目的耗时
代码:
#include<bits/stdc++.h>
using namespace std;
int n;
int help(int n){
int sum=0,w[25],dp[1205]={0};
for(int i=1;i<=n;i++)
cin>>w[i],sum+=w[i];
for(int i=1;i<=n;i++)
for(int j=sum/2;j>=w[i];j--)
dp[j]=max(dp[j],dp[j-w[i]]+w[i]);
return sum-dp[sum/2];
}
int main() {
int s1,s2,s3,s4,ans=0;
cin>>s1>>s2>>s3>>s4;
ans=help(s1)+help(s2)+help(s3)+help(s4);
cout<<ans;
return 0;
}
T 4 : P 2347 \tt T4:P2347 T4:P2347
这题是多重背包模版加找答案,很简单。
但不过注意第二层循环
j
j
j 一定是从
1000
1000
1000 循环到
0
0
0!!!(我就是因为这个丢了92分)
代码:
#include<iostream>
using namespace std;
int num[7],ans,w[]={0,1,2,3,5,10,20},dp[1005];
int main()
{
dp[0]=1;
for(int i=1;i<=6;i++)
{
cin>>num[i];
}
for(int i=1;i<=6;i++)
{
for(int j=1000;j>=0;j--)
{
for(int k=0;k<=num[i];k++)
{
if(j>=k*w[i])
{
dp[j]+=dp[j-w[i]*k];
}
}
}
}
for(int i=1;i<=1000;i++)
{
if(dp[i]!=0)
{
ans++;
}
}
cout<<"Total="<<ans;
return 0;
}