您的位置:首页 > 其它

ACdream 1070 神奇的%系列二(YM)

2015-05-02 01:05 218 查看
对数据进行离线处理。
这边主要是要能够想到区间的建边问题,学习了,YM大神
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
#define MAX 110000
vector<int>f[MAX];
int a[MAX];
int num2[MAX];
int ans[MAX];
int head[MAX];
int prim[1100];
int num[1100];
int cur;
int cnt;
int cnt2;
struct edge
{
int u, x;
int id;
int next;
}edg[MAX<<1];
void init()
{
cnt2 = 0;
memset(head, -1, sizeof head);
}

void addedge(int u, int v, int id)
{
edg[cnt2].u = u;
edg[cnt2].x = v;
edg[cnt2].id = id;
edg[cnt2].next = head[u];
head[u] = cnt2++;
}
//动态获取一个数的因子的方法
void dfs(int id, int now,int s)
{
for (int i = id; i < cnt; i++)
{
int k = now;
for (int j = 1; j <= num[i]; j++)
{
k *= prim[i];
f[s].push_back(k);
dfs(i + 1, k, s);
}
}
}

void get_prim(int x)
{
for (int i = 2; i*i <= x; i++)
{
if (x%i == 0)
{
prim[cnt] = i;
num[cnt] = 0;
while (x%i == 0)
{
x /= i;
num[cnt]++;
}
cnt++;
}

}
if (x != 1)
if (x != prim[cnt - 1])
{
prim[cnt] = x;
num[cnt] = 1;
cnt++;
}
else
num[cnt]++;
}
void gao()
{
for (int i = 1; i < MAX; i++)
{
f[i].push_back(1);
cnt = 0;
get_prim(i);
dfs(0, 1, i);
}
}
void get_fac(){
for (int i = 1; i<MAX; i++)
for (int j = i; j<MAX; j += i)
f[j].push_back(i);

}

int main()
{
int n;
gao();
while (~scanf("%d", &n))
{
memset(num2, 0, sizeof num2);
init();
for (int i = 1; i <= n; i++)
scanf("%d", &a[i]);
int m;
scanf("%d", &m);
int l, r,x;
cnt2 = 0;
for (int i = 0; i < m; i++)
{
scanf("%d%d%d", &l, &r, &x);
addedge(l - 1, x, i);
addedge(r, x, i);
}
int k = 1;
memset(ans, 0, sizeof ans);
int res;
for (int i = 1; i <= n; i++)
{
num2[a[i]]++;
for (int j = head[i]; j != -1; j = edg[j].next)
{
res = 0;
int s = edg[j].u;
int X = edg[j].x;
int len = f[X].size();
for (int k = 0; k < len; k++)
res  += num2[f[X][k]];
if (ans[edg[j].id])
ans[edg[j].id] = res - ans[edg[j].id];
else
ans[edg[j].id] = res;
}
}
for (int i = 0; i < m; i++)
printf("%d\n", ans[i]);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: