您的位置:首页 > 其它

动态规划_ 选出一些数相加,问最后是m的倍数的方案有多少种

2015-09-24 15:29 483 查看
题意:给定n个数,让你判断是否能从中选出一些数相加,使得他们的和能够整除m;

分析:这类dp状态转移感觉比较好想,可以从第一项开始每次都把他的结果记录下来,然后轮到后面某一项的时候,直接利用前面的结果进行状态转移。注意记录结果的时候不能直接更新dp数组,因为这样会导致这一项被重复利用。可以享用数组保存下来,后来在更新。

http://codeforces.com/contest/577/problem/B



B. Modulo Sum

time limit per test
2 seconds

memory limit per test
256 megabytes

input
standard input

output
standard output

You are given a sequence of numbers a1, a2, ..., an, and a numberm.

Check if it is possible to choose a non-empty subsequence
aij such that the sum of numbers in this subsequence is divisible bym.

Input
The first line contains two numbers, n andm (1 ≤ n ≤ 106,2 ≤ m ≤ 103)
— the size of the original sequence and the number such that sum should be divisible by it.

The second line contains n integers
a1, a2, ..., an (0 ≤ ai ≤ 109).

Output
In the single line print either "YES" (without the quotes) if there exists the sought subsequence, or "NO" (without the quotes), if such subsequence doesn't exist.

Sample test(s)

Input
3 5
1 2 3


Output
YES


Input
1 6
5


Output
NO


Input
4 6
3 1 1 3


Output
YES


Input
6 6
5 5 5 5 5 5


Output
YES


Note
In the first sample test you can choose numbers 2 and3, the sum of which is divisible by
5.

In the second sample test the single non-empty subsequence of numbers is a single number5. Number
5 is not divisible by6, that is, the sought subsequence doesn't exist.

In the third sample test you need to choose two numbers
3 on the ends.

In the fourth sample test you can take the whole subsequence.

#include<bitset>
#include<map>
#include<vector>
#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
#include<stack>
#include<queue>
#include<set>
#define inf 0x3f3f3f3f
#define mem(a,x) memset(a,x,sizeof(a))

using namespace std;

typedef long long ll;
typedef pair<int,int> pii;

inline int in()
{
int res=0;char c;
while((c=getchar())<'0' || c>'9');
while(c>='0' && c<='9')res=res*10+c-'0',c=getchar();
return res;
}
const int N=1000010;

int a
;
int dp
;
int v
;
int main()
{
int n=in(),mod=in();
for(int i=0;i<n;i++)
{
a[i]=in()%mod;
}

for(int i=0;i<n && !dp[0];i++)
{
int cnt=0;
for(int j=0;j<mod && !dp[0];j++)
{
if(dp[j])
{
v[cnt++]=((j+a[i])%mod);//不能直接更新dp数组,先把结果记录下来
}
}
for(int j=0;j<cnt;j++)
{
dp[v[j]]=1;
}
dp[a[i]]=1;
}
puts(dp[0]?"YES" : "NO");
return 0;
}


Clarke and problem

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)

Total Submission(s): 653 Accepted Submission(s): 272

[align=left]Problem Description[/align]
Clarke is a patient with multiple personality disorder. One day, Clarke turned into a student and read a book.

Suddenly, a difficult problem appears:

You are given a sequence of number a1,a2,...,an
and a number p.
Count the number of the way to choose some of number(choose none of them is also a solution) from the sequence that sum of the numbers is a multiple ofp(0
is also count as a multiple of p).
Since the answer is very large, you only need to output the answer modulo
109+7

[align=left]Input[/align]
The first line contains one integer
T(1≤T≤10)
- the number of test cases.

T
test cases follow.

The first line contains two positive integers n,p(1≤n,p≤1000)

The second line contains n
integers a1,a2,...an(|ai|≤109).

[align=left]Output[/align]
For each testcase print a integer, the answer.

[align=left]Sample Input[/align]

1
2 3
1 2


[align=left]Sample Output[/align]

2

Hint:
2 choice: choose none and choose all.


[align=left]Source[/align]
BestCoder Round #56 (div.2)

http://acm.hdu.edu.cn/showproblem.php?pid=5464

题意:给定n个数,存在负数,让你求出重中选出一些数能够整除m的方案数。

分析:数据中有负数,直接模m再加上m就能变成正数。然后记录结果,逐项递推。

#include<bitset>
#include<map>
#include<vector>
#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
#include<stack>
#include<queue>
#include<set>
#define inf 0x3f3f3f3f
#define mem(a,x) memset(a,x,sizeof(a))

using namespace std;

typedef long long ll;
typedef pair<ll ,ll > pii;

inline int in()
{
int res=0;char c;
while((c=getchar())<'0' || c>'9');
while(c>='0' && c<='9')res=res*10+c-'0',c=getchar();
return res;
}
const int N=100010;

int a[1001];
ll dp[1111];
pii v[1111];

const int mod=1e9+7;
int main()
{
int T=in();
while(T--)
{
int n=in(),p=in();

for(int i=0;i<n;i++)
{
scanf("%d",&a[i]);
if(a[i]<0) a[i]=a[i]%p+p;
else a[i]%=p;
}
int cnt;
mem(dp,0);
dp[0]=1;
for(int i=0;i<n;i++)
{
cnt=0;
for(int j=0;j<p;j++)
{
if(dp[j])
{
ll tmp=(a[i]+j)%p;
v[cnt++]=pii(tmp,dp[j]);
}
}
for(int j=0;j<cnt;j++)
{
dp[v[j].first]=(dp[v[j].first]+v[j].second)%mod;
//if(dp[v[j].first]>=mod) dp[v[j].first]-=mod;
}

}

printf("%d\n",dp[0]);
}
return 0;
}


Happy Matt Friends

Time Limit: 6000/6000 MS (Java/Others) Memory Limit: 510000/510000 K (Java/Others)

Total Submission(s): 1380 Accepted Submission(s): 547



[align=left]Problem Description[/align]

Matt has N friends. They are playing a game together.

Each of Matt’s friends has a magic number. In the game, Matt selects some (could be zero) of his friends. If the xor (exclusive-or) sum of the selected friends’magic numbers is no less than M , Matt wins.

Matt wants to know the number of ways to win.

[align=left]Input[/align]

The first line contains only one integer T , which indicates the number of test cases.

For each test case, the first line contains two integers N, M (1 ≤ N ≤ 40, 0 ≤ M ≤ 106).

In the second line, there are N integers ki (0 ≤ ki ≤ 106), indicating the i-th friend’s magic number.

[align=left]Output[/align]

For each test case, output a single line “Case #x: y”, where x is the case number (starting from 1) and y indicates the number of ways where Matt can win.

[align=left]Sample Input[/align]

2
3 2
1 2 3
3 3
1 2 3


[align=left]Sample Output[/align]

Case #1: 4
Case #2: 2

HintIn the first sample, Matt can win by selecting:
friend with number 1 and friend with number 2. The xor sum is 3.
friend with number 1 and friend with number 3. The xor sum is 2.
friend with number 2. The xor sum is 2.
friend with number 3. The xor sum is 3. Hence, the answer is 4.


[align=left]Source[/align]

2014ACM/ICPC亚洲区北京站-重现赛(感谢北师和上交)

http://acm.hdu.edu.cn/showproblem.php?pid=5119

题意:给定n个数,求从中选出一些数,求选出的数中小于m的方案数。
分析:这题跟前面两题差不多,也是从每一项开始递推,记录结果,然后更新dp数组。

#include<bitset>
#include<map>
#include<vector>
#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
#include<stack>
#include<queue>
#include<set>
#define inf 0x3f3f3f3f
#define mem(a,x) memset(a,x,sizeof(a))

using namespace std;

typedef long long ll;
typedef pair<int,int> pii;

inline int in()
{
int res=0;char c;
while((c=getchar())<'0' || c>'9');
while(c>='0' && c<='9')res=res*10+c-'0',c=getchar();
return res;
}
const int N=1111111;

int dp
;
pii v
;
int a[44];

int main()
{
int T=in();
int ii=1;
while(T--)
{
int n=in(),m=in();
for(int i=1;i<=n;i++)
{
a[i]=in();
}
mem(dp,0);

dp[0]=1;
int cnt=0,tmp;

for(int i=1;i<=n;i++)
{
cnt=0;
for(int j=0;j<N;j++)
{
if(dp[j]) v[cnt++]=pii(j^a[i],dp[j]);
}
for(int j=0;j<cnt;j++)
{
dp[v[j].first]+=v[j].second;
}
}
ll ans=0;
for(int i=m;i<N;i++)
{
ans+=dp[i];
}
printf("Case #%d: %I64d\n",ii++,ans);

}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: