[Gym-101981J] Prime Game (组合计数)

题意:求for(int i=1;i<=n;i++) for(int j=i;j<=n;j++) sum += f[i][j]; f[i][j]表示在序列从 i 位乘到第 j 位所形成的新的数的 不同质因子的个数.

思路:说是话,拿到题还是一开始想着能不能进行递推,比如先将每一个数进行 质因分解 然后用set不断更新统计个数来求和。但这样无论怎样都无法优化 (n^2) ,所以换思路再想。

就忽然想到了以前有一道做过的原题,题意是:给定一个长度为n的序列,然后求出每一个子区间不同数的个数和。而这一道题就是组合计数,计算每一个位置上的值对最后区间计数所产生的贡献。

而这道题类似,略微修改即是每一个位置上不只一个值(分解可能得到多个质因子),所以就用set来存放。

上面这幅图,坐标轴上表示坐标,坐标轴下表示每个位置set所存放对应数的质因子数。比如我们对所有位置的5的贡献值进行计算。

位置坐标2:由于这个5要产生贡献,即其左边起始下标要从 1 开始,直到它本身的坐标 2. 其右边的开始坐标从它本身开始 2 一直延申到坐标轴右端. 所以 左 x 右 = (2-0) x (7-2+1) = 10;

位置坐标4:要使这个位置的5产生贡献,由于我们对上一个5右边所有区间进行了计算,所以在计算这个5的贡献的时候我们要从它上一个5的位置的下一位开始到它本身,即从 3-4,而其右端也是延申到右端点,所以 (4-2) x (7-4+1) = 8;

所以计算某个数的贡献,即 其左边第一个出现的下一位开始到他本身位置为左端点取值范围,从他本身开始到坐标轴右端点为其区间右端点取值范围,而左乘以右则为所有区间贡献总和。

#include <bits/stdc++.h>
#define IOS ios::sync_with_stdio(0); cin.tie(0);
#define mp make_pair
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
const double Pi = acos(-1.0);
const double esp = 1e-9;
const int inf = 0x3f3f3f3f;
const int maxn = 1e5+7;
const int maxm = 1e6+7;
const int mod = 1e9+7;
//所有模板默认 prime[],powe[]从下标0开始取
const int MAXL = 1e6+7;
//int phi[MAXL];//欧拉函数
int tot;
int prim[MAXL];//素数表
int cnt;
int vis[MAXL];
//int powe[MAXL];//质数幂
int cur;
int pp[maxm];

set<int>qq[maxm];
set<int>::iterator it;
int a[maxm];
int getPrime(){
    int i ,j;
    int cnt = 0;
    memset(vis,0,sizeof(0));
    vis[0] = vis[1] = 1;
    for(i=2;i<=MAXL;++i)
    {
        if(!vis[i]) vis[i]= prim[cnt++]= i;
        for(j=0;j<cnt&&i*prim[j]<=MAXL;++j){
            vis[i*prim[j]] = 1;
            if(i%prim[j]==0) break;
        }
    }
    return cnt;
}
int getfac(int n,int cnt,int pos){
    for(int i=0;prim[i]*prim[i]<=n;i++){
        if(n%prim[i]==0) {
            qq[pos].insert(prim[i]);
            pp[prim[i]] = 0;
            while(n%prim[i]==0) n /= prim[i];
        }
    }
    if(n>1) qq[pos].insert(n);
}
int main(){
    int n;
    scanf("%d",&n);
    cnt = getPrime();
    for(int i=1;i<=n;i++){
        scanf("%d",a+i);
        getfac(a[i],cnt,i);
    }
    ll sum = 0;
    for(int i=1;i<=n;i++){
        for(it = qq[i].begin();it != qq[i].end(); it++){
            int tmp = *it;
            int k = pp[tmp];
            pp[tmp] = i;
            sum += (ll) (i-k)*(n-i+1);
        }
    }
    printf("%lld\n",sum);

} 

原文地址:https://www.cnblogs.com/Tianwell/p/11668124.html

时间: 2024-11-06 12:26:05

[Gym-101981J] Prime Game (组合计数)的相关文章

[HDU 3461] Saving Beans &amp; 组合计数Lucas定理模板

Saving Beans Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Problem Description Although winter is far away, squirrels have to work day and night to save beans. They need plenty of food to get through those long cold

【51nod】1222 最小公倍数计数 莫比乌斯反演+组合计数

[题意]给定a和b,求满足a<=lcm(x,y)<=b && x<y的数对(x,y)个数.a,b<=10^11. [算法]莫比乌斯反演+组合计数 [题解]★具体推导过程参考:51nod1222 最小公倍数计数 过程运用到的技巧: 1.将所有i和j的已知因子提取出来压缩上届. 2.将带有μ(k)的k提到最前面,从而后面变成单纯的三元组形式. 最终形式: $$ans=\sum_{k=1}^{\sqrt n} \mu(k)  \sum_{d}    \sum_{i} \s

Yue Fei&#39;s Battle(组合计数递推)

//求一个直径为 k 的树有多少种形态,每个点的度不超过 3 // 非常完美的分析,学到了,就是要细细推,并且写的时候要细心 还有除法取模需要用逆元 #include <iostream> #include <stdio.h> #include <string.h> #include <math.h> #include <stdlib.h> using namespace std; #define MOD 1000000007 #define L

POJ 1496 POJ 1850 组合计数

Code Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 8256 Accepted: 3906 Description Transmitting and memorizing information is a task that requires different coding systems for the best use of the available space. A well known system is t

bzoj 1004 Cards 组合计数

这道题考察的是组合计数(用Burnside,当然也可以认为是Polya的变形,毕竟Polya是Burnside推导出来的). 这一类问题的本质是计算置换群(A,P)中不动点个数!(所谓不动点,是一个二元组(a,p),a∈A,p∈P ,使得p(a)=a,即a在置换p的作用后还是a). Polya定理其实就是告诉了我们一类问题的不动点数的计算方法. 对于Burnside定理的考察,我见过的有以下几种形式(但归根结底还是计算不动点数): 1.限制a(a∈A)的特点,本题即是如此(限制了各颜色个数,可以

POJ 3252 组合计数

Round Numbers Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 9149 Accepted: 3248 Description The cows, as you know, have no fingers or thumbs and thus are unable to play Scissors, Paper, Stone' (also known as 'Rock, Paper, Scissors', 'Ro,

HDU4675-GCD of Sequence(数论+组合计数)

GCD of Sequence Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others) Total Submission(s): 949    Accepted Submission(s): 284 Problem Description Alice is playing a game with Bob. Alice shows N integers a1, a2, -, aN, an

POJ 1019 组合计数

链接:POJ 1019 /***************************************** author : Grant Yuan time : 2014/10/19 14:38 source : POJ 1019 algorithm: 组合计数 ******************************************/ #include <iostream> #include <cstdio> #include <algorithm> #

HDU 4832 组合计数dp

Chess Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 509    Accepted Submission(s): 198 Problem Description 小度和小良最近又迷上了下棋.棋盘一共有N行M列,我们可以把左上角的格子定为(1,1),右下角的格子定为(N,M).在他们的规则中,"王"在棋盘上的走法遵循十字