【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); } } }
相关文章推荐
- HYSBZ 1036 树的统计Count (树链剖分 + 线段树)
- 面试总结
- 8086汇编语言自学经验分享 用栈与push指令往1000:0000处写入1234H
- java怎样把后台值传到前台
- pax boot map (1)
- 第一步:SIFT尺度空间的建立--FPGA设计完成
- Longest Valid Parentheses
- 关于TabActivity的使用
- MediaCodec与ACodec通知分析
- 如果我能够说话的话,我会对你说
- Spring与Hibernate整合中的数据源配置
- IP地址和数字之间转化的算法
- 查看linux 下已经安装的软件包信息
- Js实现文件上传无刷新以及图片预览
- 基于随机森林的特征选择算法
- Excel Sheet Column Number
- JS 根据今天的日期获取本周星期一与星期天的日期
- Poj 1947 Rebuilding Roads
- C++11的新特性简单汇总介绍 (二)
- 搜索引擎研究---网络蜘蛛程序算法相关资料 Part V (共5部分)