您的位置:首页 > 其它

【NOIP模拟】第三条跑道

2016-07-18 09:18 134 查看

Description



Solution

一看到这种题就是数据结构。

欧拉函数的公式

看到求很多歌欧拉函数就要想到欧拉函数的公式。

φ(x)=x∗p1−1p1∗p2−1p2∗......∗pk−1pk

用什么维护

很明显的是600以内的质数的个数很少,只有110个左右。

那么对每个数分解质因数就好了。

然后开110个左右棵线段树,存每个质数在这段区间内的覆盖面积(因为欧拉函数公式后面的那一段指数都为1且pi≠pj,所以每个质数覆盖了一个点只会+1),然后为了算很多个数相乘,顺便的把所有质数分解后在一段区间内指数的和给算进去就可以了。

因为要除法,所以用一个费马小定理来求逆元。

比赛本来可以AC的,标记下传的时候某个+=达成了=TATATATATAT

Code

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
typedef long long ll;
int i,j,k,l,n,m;
const int maxn=10007,mo=100000007;
bool bz[maxn];
int x,y,root[maxn],num;
ll ans,mu,zi,zhi[maxn],a[maxn],p,mi;
struct node{
int l,r,sum,add,ci,bi;
}t[maxn*600];
ll qsc(ll x,ll y){
ll a1=x/1000000,a2=x%1000000,b1=y/1000000,b2=y%1000000,z=0;
z=(a1*b1%mo*1000000%mo*1000000%mo);
z=(z+a1*b2%mo*1000000%mo);
z=(z+a2*b2%mo);
z=(z+a2*b1%mo*1000000%mo);
return z%mo;
}
ll qsm(ll x,ll y){
ll z=1;
while(y){
if(y&1)z=z*x%mo;
x=x*x%mo;
y/=2;
}
return z;
}
ll chu(ll x,ll y){
y=qsm(y,mo-2);
x=qsc(x,y)%mo;
return x;
}
void down(int x,int l,int r){
if(t[x].add){
if(!t[x].l)t[x].l=++num;
if(!t[x].r)t[x].r=++num;
t[t[x].l].add=t[t[x].r].add=t[x].add;
t[t[x].l].bi+=t[x].bi;t[t[x].r].bi+=t[x].bi;
int mid=(l+r)/2;
t[t[x].l].sum=t[x].add*(mid-l+1);
t[t[x].r].sum=t[x].add*(r-mid);
t[t[x].l].ci+=t[x].bi*(mid-l+1);
t[t[x].r].ci+=t[x].bi*(r-mid);
t[x].add=0;
t[x].bi=0;
}
}
void change(int &x,int l,int r,int y,int z,int o){
if(!x)x=++num;
if(l==y&&r==z){
t[x].add=1;t[x].sum=r-l+1;
t[x].ci+=o*(r-l+1);t[x].bi+=o;
return;
}
down(x,l,r);
int mid=(l+r)/2;
if(z<=mid)change(t[x].l,l,mid,y,z,o);
else if(y>mid)change(t[x].r,mid+1,r,y,z,o);
else{
change(t[x].l,l,mid,y,mid,o);
change(t[x].r,mid+1,r,mid+1,z,o);
}
t[x].sum=t[t[x].l].sum+t[t[x].r].sum;
t[x].ci=t[t[x].l].ci+t[t[x].r].ci;
}
int find(int x,int l,int r,int y,int z){
if(l==y&&r==z){
mi+=t[x].ci;
return t[x].sum;
}
down(x,l,r);
int mid=(l+r)/2;
if(z<=mid)return find(t[x].l,l,mid,y,z);
else if(y>mid)return find(t[x].r,mid+1,r,y,z);
else{
return find(t[x].l,l,mid,y,mid)+find(t[x].r,mid+1,r,mid+1,z);
}
t[x].sum=t[t[x].l].sum+t[t[x].r].sum;
t[x].ci=t[t[x].l].ci+t[t[x].r].ci;
}
int main(){
//  freopen("fan.in","r",stdin);
fo(i,2,600){
if(!bz[i]){
fo(j,2,600/i)bz[i*j]=1;
zhi[++zhi[0]]=i;
}
}
scanf("%d",&n);
fo(i,1,n){
scanf("%d",&x);
int u=x;
fo(j,1,zhi[0]){
if(!(u%zhi[j])){
int o=0;
while(!(u%zhi[j]))o++,u/=zhi[j];
change(root[j],1,n,i,i,o);
if(u==1)break;
}
}
}
scanf("%d",&m);
while(m--){
scanf("%d%d%d",&k,&x,&y);
if(k==0){
scanf("%d",&l);
int u=l;
fo(j,1,zhi[0]){
if(!(u%zhi[j])){
int o=0;
while(!(u%zhi[j]))o++,u/=zhi[j];
change(root[j],1,n,x,y,o);
//  if(u==1)break;
}
}
}
else{
mu=1;
fo(i,1,zhi[0]){
mi=0;
p=find(root[i],1,n,x,y);
mu=mu*qsm(zhi[i]-1,p)%mo*qsm(zhi[i],mi)%mo;
zi=qsm(zhi[i],p);
mu=chu(mu,zi);
}
printf("%lld\n",mu);
}
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: