SPOJ AMR10I Dividing Stones 简单深搜

题目链接:http://www.spoj.com/problems/AMR10I/

题目大意:把一个数N(N<70),分成几个数和的形式,再把这几个数相乘,问有多少种不同的乘积(种数对p取模)?

样例:

CONSTRAINTS
T <= 20 
2 <= N <= 70 
2 <= P <= 1e9 
 
SAMPLE INPUT

3 1000 
5 1000 
 
SAMPLE OUTPUT 


 
EXPLANATION
In the first test case, the possible ways of division are (1,1,1), (1,2), (2,1) and (3) which have values 1, 2, 2, 3 and hence, there are 3 distinct values. 
In the second test case, the numbers 1 to 6 constitute the answer and they can be obtained in the following ways: 
1=1*1*1*1*1 
2=2*1*1*1 
3=3*1*1 
4=4*1 
5=5 
6=2*3

解题思路:因为任何一个数都可以分成若干个素数的乘积(1除外);那么只需要深搜枚举70以内的素数乘积即可,同时维护和为 N。其中用set容器去重。

代码如下:

#include<stdio.h>
#include<set>
#include<algorithm>
using namespace std;
int n,p;
set<long long> S;
int pr[]={2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73};
void dfs(int x,int n,long long ji)
{
    S.insert(ji);
    if(pr[x]>n) return;
    dfs(x,n-pr[x],ji*pr[x]%p);//取第x个素数
    dfs(x+1,n,ji);//从第x+1个素数深搜
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        S.clear();
        scanf("%d%d",&n,&p);
        dfs(0,n,1);
        printf("%d\n",S.size());
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值