Codeforces 893E - Counting Arrays

893E - Counting Arrays

思路:质因子分解。

对于每个质因子,假设它有k个,那么求把它分配到y个数上的方案数。

相当于把k个小球分配到y个盒子里的方案数。

这个问题可以用隔板法(插空法)解决,要把一段分成y段,需要y-1个隔板,那么有y-1+k个位置,选y-1个位置为隔板,剩下的都是小球,那么方案数为C(y-1+k,y-1)。

如果全为正数,答案就是所有质因子方案数的积。

但是这道题目可以为负数,那么在这y个数里选偶数个变成负数

答案还要乘以C(y,0)+C(y,2)+C(y,4)+C(y,6)+...                              ③

这个问题是高中排列组合的一个经典问题,

设(1+x)^y=C(y,0)*x^0+C(y,1)*x^1+...+C(y,y-1)*x^(y-1)+C(y,y)*x^y

当x=1时,C(y,0)+C(y,1)+...+C(y,y-1)+C(y,y)=2^y                       ①

当x=-1时,C(y,0)-C(y,1)+C(y,2)-C(y-3)+...=0                             ②

①+②=2*③

③式为2^(y-1)

代码:

By ZhihuiLiu, contest: Educational Codeforces Round 33 (Rated for Div. 2), problem: (E) Counting Arrays, Accepted, #, hack it!

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pb push_back
#define mem(a,b) memset(a,b,sizeof(a))

const int MOD=1e9+7;
const int N=1e6+5;
ll fac[2*N];
ll q_pow(ll n,ll k)
{
    ll ans=1;
    while(k)
    {
        if(k&1)ans=(ans*n)%MOD;
        n=(n*n)%MOD;
        k>>=1;
    }
    return ans;
}
void init()
{
    fac[0]=1;
    for(int i=1;i<2*N;i++)fac[i]=(fac[i-1]*i)%MOD;
}
ll C(ll n,ll m)
{
    return (fac[n]*q_pow(fac[m],MOD-2))%MOD*q_pow(fac[n-m],MOD-2)%MOD;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    int q,x,y;
    init();
    cin>>q;
    while(q--)
    {
        cin>>x>>y;
        int c=0;
        ll ans=q_pow(2,y-1);
        for(int i=2;i*i<=x;i++)
        {
            if(x%i==0)
            {
                int t=0;
                while(x%i==0)
                {
                    t++;
                    x/=i;
                }
                ans=(ans*C(t+y-1,t))%MOD;
            }
        }
        if(x>1)ans=(ans*y)%MOD;
        cout<<ans<<endl;
    }
    return 0;
}
时间: 2024-07-30 00:26:08

Codeforces 893E - Counting Arrays的相关文章

Codeforces 893E Counting Arrays:dp + 线性筛 + 分解质因数 + 组合数结论

题目链接:http://codeforces.com/problemset/problem/893/E 题意: 共q组数据(q <= 10^5),每组数据给定x,y(x,y <= 10^6). 问你有多少种长度为y,乘积为x的整数数列.(可以有负数) 题解: 首先考虑数列只有正整数的情况. 将x分解质因数:x = ∑ a[i]*p[i] 由于x较大,所以要先用线性筛求出素数,再枚举素数分解质因数. 那么一个乘积为x的数列可以看做,将x的所有∑ p[i]个质因子,分配到了y个位置上. 设f(i)

codeforces 372A Counting Kangaroos is Fun

There are n kangaroos with pockets. Each kangaroo has a size (integer number). A kangaroo can go into another kangaroo's pocket if and only if the size of kangaroo who hold the kangaroo is at least twice as large as the size of kangaroo who is held.

Codeforces 372B Counting Rectangles is Fun

http://codeforces.com/problemset/problem/372/B 题意:每次给出一个区间,求里面有多少个矩形 思路:预处理,sum[i][j][k][l]代表以k,l为右下角,左上角不超过i,j有多少矩形,然后询问的时候枚举右下角就可以了 1 #include<cstdio> 2 #include<cmath> 3 #include<algorithm> 4 #include<cstring> 5 #include<iost

codeforces 1140E Palindrome-less Arrays

题目链接:http://codeforces.com/contest/1140/problem/E 题目大意: 如果一个数组的存在一个奇数长的回文就不好. 不是不好的数组是好的. 你可以把-1用1到k中一个数替换.问可以有多少种不同的好数组. 开虚拟赛最后一分钟把它A了,很开心,很开心. 思路: 我们翻译一下,如果存在长度为5的回文就必须会出现长度为3的回文. 也就是说不能出现长度为3回文. 也就是说x[i]!=x[i+2],x[i]!=x[i-2];(x[i]为输入数组) 那我们把数组分为两个

Codeforces 372B. Counting Rectangles is Fun【动态规划,暴力枚举】(lowbit()小用法)

题目大意: 给出一个由0,1构成的矩阵,询问(a,b)到(c,d)两个点之间的只含有0的矩形有多少个. 方法: 由于矩阵不大,最多40*40,而且询问量很大(10^5)由此我们考虑o(1)输出答案,首先用一个四维数组预处理出答案,最后直接输出即可. 令dp[a][b][c][d]为(a,b)到(c,d)两个点之间的只含有0的矩形的数量, 则递推的公式: dp[a][b][c][d]=dp[a][b][c][d-1]+dp[a][b][c-1][d]-dp[a][b][c-1][d-1] 每次计算

Educational Codeforces Round 33

Chess For Three Beautiful Divisors Rumor Credit Card Counting Arrays Subtree Minimum Query

为什么数组角标从0开始

背景 我们知道大部分编程语言中的数组都是从0开始编号的,即array[0]是数组的第一个元素.这个和我们平时生活中从1开始编号的习惯相比显得很反人类.那么究竟是什么样的原因让大部分编程语言数组都遵从了这个神奇的习惯呢?本文最初是受stackoverflow上的一个问题的启发,通过搜集和阅读了一些资料在这里做个总结.当然,本文摘录较多的过程结论,如果你想把这篇文章当做快餐享用的话,可以直接跳到文章末尾看结论. 最早的原因 在回答大部分我们无法解释的诡异问题时,我们最常用的辩词通常是历史原因.那么,

Codeforces 309C Memory for Arrays 二进制模拟进位

题目链接:点击打开链接 题意: 给定n个箱子m个物品 下面n个数字表示箱子的容量 下面m个数字b1-bm 表示物品体积为2^bi大 问最多有多少个物品可以放入箱子. 思路: 贪心,先放小的,小的不能放再放大的 显然我们把n个箱子拆成二进制,然后模拟二进制减法运算. 剩下就是简单模拟 #include<stdio.h> #include<string.h> #include<iostream> #include<algorithm> #include<m

Educational Codeforces Round 80 (Rated for Div. 2)(C - Two Arrays )

C - Two Arrays 题目链接:https://codeforces.com/contest/1288/problem/C 题目: 题意:给你n,m,利用1~n之间的数(可重复)来组成长度为m的数组a,b,要求数组a非递减,数组b非递增,且a数组的数<=b数组中的数,求出a,b数组对数 思路:用动态规划,dp[i][j]是第i个位置放数字j的方案数,根据题意可以将b数组反置然后接在a后面,则该数组长度为2m,为一个非递减序列,则就是求1~n这些数字可重复组成多少种长度为2m的非递减序列,