bzoj3813 奇数国

http://www.elijahqi.win/archives/2960
Description

在一片美丽的大陆上有100000个国家,记为1到100000。这里经济发达,有数不尽的账房,并且每个国家有一个银行。某大公司的领袖在这100000个银行开户时都存了3大洋,他惜财如命,因此会不时地派小弟GFS清点一些银行的存款或者让GFS改变某个银行的存款。该村子在财产上的求和运算等同于我们的乘法运算,也就是说领袖开户时的存款总和为3100000。这里发行的软妹面额是最小的60个素数(p1=2,p2=3,…,p60=281),任何人的财产都只能由这60个基本面额表示,即设某个人的财产为fortune(正整数),则fortune=p1^k1*p2^k2*……p60^K60。

领袖习惯将一段编号连续的银行里的存款拿到一个账房去清点,为了避免GFS串通账房叛变,所以他不会每次都选择同一个账房。GFS跟随领袖多年已经摸清了门路,知道领袖选择账房的方式。如果领袖选择清点编号在[a,b]内的银行财产,他会先对[a,b]的财产求和(计为product),然后在编号属于[1,product]的账房中选择一个去清点存款,检验自己计算是否正确同时也检验账房与GFS是否有勾结。GFS发现如果某个账房的编号number与product相冲,领袖绝对不会选择这个账房。怎样才算与product不相冲呢?若存在整数x,y使得number*x+product*y=1,那么我们称number与product不相冲,即该账房有可能被领袖相中。当领袖又赚大钱了的时候,他会在某个银行改变存款,这样一来相同区间的银行在不同的时候算出来的product可能是不一样的,而且领袖不会在某个银行的存款总数超过1000000。

现在GFS预先知道了领袖的清点存款与变动存款的计划,想请你告诉他,每次清点存款时领袖有多少个账房可以供他选择,当然这个值可能非常大,GFS只想知道对19961993取模后的答案。

Input

第一行一个整数x表示领袖清点和变动存款的总次数。
接下来x行,每行3个整数ai,bi,ci。ai为0时表示该条记录是清点计划,领袖会清点bi到ci的银行存款,你需要对该条记录计算出GFS想要的答案。ai为1时表示该条记录是存款变动,你要把银行bi的存款改为ci,不需要对该记录进行计算。

Output

输出若干行,每行一个数,表示那些年的答案。

Sample Input

6
013
115
013
117
013
023
Sample Output

18
24
36
6
explanation

初始化每个国家存款都为3;

1到3的product为27,[1,27]与27不相冲的有18个数;
1的存款变为5;
1到3的product为45,[1,45]与45不相冲的有24个数;
1的存款变为7;
1到3的product为63,[1,63]与63不相冲的有36个数;
2到3的product为9,[1,9]与9不相冲的有6个数。

HINT

x≤100000,当ai=0时0≤ci−bi≤100000

Source

2015年国家集训队测试

开60个树状数组 每个树状数组记录的是这个质数在该位数上出现的次数 那么直接算欧拉函数因为其积性函数的性质所以可以将欧拉函数分别算60个质因数的欧拉函数 然后乘起来即可对于单个质因数的欧拉函数计算公式即为p^k*(p-1)/p

#include<cstdio>
#include<cctype>
#include<algorithm>
#define mod 19961993
#define N 100010
#define ll long long
using namespace std;
inline char gc(){
    static char now[1<<16],*S,*T;
    if(T==S){T=(S=now)+fread(now,1,1<<16,stdin);if (T==S) return EOF;}
    return *S++;
}
inline int read(){
    int x=0,f=1;char ch=gc();
    while(!isdigit(ch)) {if (ch=='-') f=-1;ch=gc();}
    while(isdigit(ch)) x=x*10+ch-'0',ch=gc();
    return x*f;
}
const int out_len=1024*1024;
char obuf[out_len],*oh=obuf;
inline void write_char(char c){
    if (oh==obuf+out_len) fwrite(obuf,1,out_len,stdout),oh=obuf;
    *oh++=c;
}
template<class T>
inline void W(T x){
    static int buf[30],cnt;
    if (!x) write_char('0');else{
        if (x<0) write_char('-'),x=-x;
        for (cnt=0;x;x/=10) buf[++cnt]=x%10+48;
        while(cnt) write_char(buf[cnt--]);
    }
}
inline void flush(){fwrite(obuf,1,oh-obuf,stdout); } 
int prime[200],nm[350],s[66][N],n,tot,pend[N],num[N];
int tab[N][66];bool not_prime[N];
inline void add(int id,int x,int v){
    while(x<=1e5) s[id][x]+=v,x+=x&-x;
}
inline int query(int id,int x){
    if (!x) return 0;
    int tmp=0;while(x) tmp+=s[id][x],x-=x&-x;return tmp;
}
inline int ksm(ll b,int t){
    ll tmp=1;for (;t;b=b*b%mod,t>>=1) if (t&1) tmp=tmp*b%mod;return tmp;
}
int main(){
    freopen("bzoj3813.in","r",stdin);
    for (int i=2;i<=3e2;++i){
        if (!not_prime[i]) prime[++tot]=i,nm[i]=tot;
        for (int j=1;prime[j]*i<=3e2;++j){
            not_prime[prime[j]*i]=1;
            if (i%prime[j]==0) break;
        }
    }
    int T=read();for (int i=1;i<=1e5;++i) add(nm[3],i,1),tab[i][nm[3]]=1;
    while(T--){static int op,a,b,tt;static ll ans;
        op=read();
        if(!op){
            ans=1;a=read(),b=read();int tmp=0;
            for (int i=1;i<=60;++i) {tmp=query(i,b)-query(i,a-1);
            if (tmp) ans=ans*ksm(prime[i],query(i,b)-query(i,a-1)-1)%mod*(prime[i]-1)%mod;}
        //  printf("%lld\n",ans);
            W(ans);write_char('\n');
        }else{
            a=read();b=read();tt=0;
            for (int i=1;i<=60;++i) if (tab[a][i]) add(i,a,-tab[a][i]),tab[a][i]=0;
            for (int i=2;i<=b;++i){
                if (b%i) continue;
                if (b%i==0) pend[++tt]=i;num[tt]=0;
                while(b%i==0) ++num[tt],b/=i;
            }
            for (int i=1;i<=tt;++i) add(nm[pend[i]],a,num[i]),tab[a][nm[pend[i]]]=num[i];
        }
    }flush();
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值