ArcTan

dfs
随笔 - 16, 文章 - 117, 评论 - 6, 引用 - 0
数据加载中……

ACdream 1159(组合-递推-优化)

1159: One Theorem, One Year

Time Limit: 1 Sec  Memory Limit: 128 MB
Submit: 21  Solved: 12
[Submit][Status][Web Board]

Description

A number is Almost-K-Prime if it has exactly K prime numbers (not necessarily distinct) in its prime factorization. For example, 12 = 2 * 2 * 3 is an Almost-3-Prime and 32 = 2 * 2 * 2 * 2 * 2 is an Almost-5-Prime number. A number X is called Almost-K-First-P-Prime if it satisfies the following criterions:

1.      X is an Almost-K-Prime and

2.      X has all and only the first P (P ≤ K) primes in its prime factorization.

For example, if K=3 and P=2, the numbers 18 = 2 * 3 * 3 and 12 = 2 * 2 * 3 satisfy the above criterions. And 630 = 2 * 3 * 3 * 5 * 7 is an example of Almost-5-First-4-Pime.

For a given K and P, your task is to calculate the summation of Φ(X) for all integers X such that X is an Almost-K-First-P-Prime.

Input

Input starts with an integer T (≤ 10000), denoting the number of test cases.

Each case starts with a line containing two integers K (1 ≤ K ≤ 500) and P (1 ≤ P ≤ K).

Output

For each case, print the case number and the result modulo

1000000007

.

Sample Input

3 3 2 5 4 99 45

Sample Output

Case 1: 10 Case 2: 816 Case 3: 49939643

求出素数后然后,然后然后就是排列组合的问题了。
dp[i][j]表示在前i个素数里选j个数相乘的和
dp[i][j]= dp[i-1][j-k]*exp[i][k]   0<=k<=j求和
这里边算边模
a[i][j]表示在前i个素数里j个数组成结果,则
a[i][j]=mul[i]*dp[i][j-1]
这里也边算模。

#include<stdio.h>
#include<string.h>
#include<math.h>
int pri
[550],b[3705];  //这里之前是3500要错哦
long long dp[505][505],a[505][505];
long long mod=1000000007;
int GetPri()
{
    int i
,j,tot;
    memset(b,0,sizeof(b));
    i=2;
    tot=0;    //写了那么素数筛法了,居然会在这里载!!!!
    while (i<=3700)
    {
        while (b
[i])    i++;
        pri[++tot]=i;
        j=i;
        while (j<=3700)
        {
            b
[j]=1;
            j+=i;
        }
    }
    return 
0;
}

int Cal()
{
    int i
,j;
    long long sum,mul;
    dp[0][0]=1;
    for (i=1; i<=500 ; i++ )
    {
        dp
[i][0]=1;
        sum=0;
        for (j=1; j<=500 ; j++ )
        {
            sum
=(sum*pri[i]+dp[i-1][j-1]*pri[i]) % mod;   //哎,方程的优化,还是没有经验啊!!这里之前我是写了个三重的循环呢。可以迭代的啊。
            dp[i][j]=(dp[i-1][j]+sum) % mod;
        }
    }
    mul
=1;
    for (i=1; i<=500 ; i++ )
    {
        mul
=mul*(pri[i]-1) % mod;    //方程优化!!!
        for (j=i; j<=500 ; j++ )
            a[i][j]=mul*dp[i][j-i] % mod;
    }
}

int main()
{
    int p
,cas,n,m;
    GetPri();
    Cal();
    scanf("%d",&p);
    cas=0;
    while (p--)
    {
        scanf(
"%d%d",&n,&m);
        printf("Case %d: %lld\n",++cas,a[m][n]);
    }
    return 
0;
}


总结:方程的优化,降低维数!!!!!!!!!!!!!!!!!!!!
真的是弱爆了啊。。。。。。。。

posted on 2012-04-29 17:15 wangs 阅读(180) 评论(0)  编辑 收藏 引用 所属分类: ACM-数学


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理