标签:
Hiiragi likes collecting sticks. It is said that she has collected m short sticks. One day, she was very excited that she found more sticks from a box under her bed. These new sticks have n different lengths, while for each length, there are infinite sticks of the same length.
Hiiragi then came up with an idea, that concatenates the new sticks in different ways to form long sticks of all possible lengths no longer than L. Let‘s name the lengths a set S.
Her mother told her that "Use each of your m short sticks to measure each of the lengths in S. When you find a short sticks being able to measure a length in integer times, get the times it takes and denote it as t. I will give you
one candy if you can find one way that uses the following rules to reduce t to 1."
So here, you are required to calculate how many candies Hiiragi can get at most.
The first line is T ( ≤ 10), the number of test cases.
Next is T test cases. Each case contains 3 lines. The first line contains three integers n, m, L (n ≤ 20, m ≤ 105, L ≤ 106). The second line is n integers indicating the lengths of
each kind of sticks found under the bed. The third line is m integers indicating the sticks Hiiragi originally had. All sticks have length no shorter than 1 and no longer than L.
For each case, print one integer, the number of candies Hiiragi can get at most.
1 2 4 12 4 6 1 3 4 3
16
In the sample, using sticks of length 4 and 6 can make long sticks of S = {4, 6, 8, 10, 12}.
So, with short stick of length 1, Hiiragi can use the following ways
4 -> 2 -> 1
6 -> 3 -> 1
6 -> 2 -> 1
8 -> 4 -> 2 -> 1
10 -> 5 -> 1
10 -> 2 -> 1
12 -> 6 -> 3 -> 1
12 -> 6 -> 2 -> 1
12 -> 4 -> 2 -> 1
to get 9 candies. Also, with short sticks of length 3, 4 and 3 she can get 2, 3 and 2 candies each. So all she can get is 9 + 2 + 3 + 2 = 16 candies.
#include <iostream> #include <stdio.h> #include <string> #include <cstring> #include <cmath> #include <vector> #include <algorithm> const int MM=1000009; typedef long long ll; using namespace std; bool dp1[MM];//只用 0 1所以用bool,节省内存,int会爆。 ll dp2[MM]; vector<int>p[MM]; int main() { int T; int n,m,L; int a; for(int i=2;i<MM;i++) if(p[i].empty()) { for(int j=i;j<MM;j+=i) p[j].push_back(i);//记下每个数的质因数 } scanf("%d",&T); while(T--) { scanf("%d%d%d",&n,&m,&L); memset(dp1,0,sizeof dp1); memset(dp2,0,sizeof dp2); dp1[0]=1;//相减后为0,表示存在这个数,所以标记为1 for(int i=0;i<n;i++) { scanf("%d",&a); for(int j=a;j<=L;j++) dp1[j]|=dp1[j-a];//求出S集合中元素,标记为1 } for(int i=0;i<m;i++) { scanf("%d",&a);//dp2[x]表示,凑成x长度的木棍的方法数 dp2[a]++;//当前存在这个长度,那么t=(x/x)=1,可以获得一个糖 } for(int i=2;i<=L;i++) { for(int j=0;j<p[i].size();j++) dp2[i]+=dp2[i/p[i][j]]; //递推过程,每次都枚举质数被 //12-(/2)->6-(/3)->2-(/2)->1,dp[12]+=dp[12/2];dp[6]已经在之前求出 //12-(/3)->4-(/2)->2-(/2)->1,dp[12]+=dp[12/3];dp[4]已经在之前求出 } ll ans=0; for(int i=1;i<=L;i++) { if(dp1[i]) ans+=dp2[i]; } printf("%lld\n",ans); } return 0; }
版权声明:本文为博主原创文章,未经博主允许不得转载。
标签:
原文地址:http://blog.csdn.net/wust_zjx/article/details/47036397