反演曾经一直是我不敢搞的一个大坑……

又重新学习了一下反演,并且做了一些习题……

大概基础什么的……我就介绍一点常用的

正经反演的式子有这样两种

$$f(n)=\sum _{d|n}F(d) \mu(\frac{n}{d})$$

以及

$$f(n)=\sum _{n|d} F(d)\mu(\frac{d}{n})$$

很多题都要用关于狄利克雷卷积的一个式子

$\mu \otimes 1 = e$,也即$\sum _{d|n} \mu(d)=[n==1]$

证明的话……我们可以用二项式定理来证,网上有很多证明,我就不证了

基本上,所有题目的转换都会利用这个式子

我们一般会搞一个$[???==1]$,然后套用上面那个关于$\sum\mu$的式子

…………板子题就不放了,每道题都挺水的

一般就是枚举$gcd$,然后判$[gcd==d]$的时候才累加,

然后除掉一个$d$变成$[gcd==1]$,然后套式子.

写一些比较有意思的题目好了。

1.bzoj3529

这题反演的式子还是可以推的……甚至说比较板子

比较好的思想是我们把询问离线按a排序,下标i按照F值排序

然后用树状数组维护答案并且更新

数学与数据结构的优秀结合……

贴代码:

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 using namespace std;
 5 typedef long long LL;
 6 const int N=100010;
 7 const unsigned int inf=0x7fffffff;
 8 bool vis[N+10];int tot;
 9 unsigned int prime[N],sumd[N+10];
10 unsigned int tmp1[N+10],tmp2[N+10],mu[N+10],p[N+10];
11 struct node{unsigned int ans,id,n,m,a;}q[20010];
12 inline bool mt1(const node &a,const node &b){return a.a<b.a;}
13 inline bool mt2(const int &a,const int &b){return sumd[a]<sumd[b];}
14 inline bool mt3(const node &a,const node &b){return a.id<b.id;}
15 inline void intn()
16 {
17     int k;mu[1]=sumd[1]=1;
18     for(int i=2;i<=N;i++)
19     {
20         if(!vis[i])
21         {
22             prime[++tot]=tmp2[i]=i;
23             sumd[i]=tmp1[i]=i+1,mu[i]=-1;
24         }
25         for(int j=1;j<=tot&&(k=i*prime[j])<=N;j++)
26         {
27             vis[k]=1;
28             if(i%prime[j]==0)
29             {
30                 tmp2[k]=tmp2[i]*prime[j],tmp1[k]=tmp1[i]+tmp2[k];
31                 sumd[k]=sumd[i]/tmp1[i]*tmp1[k];
32                 mu[k]=0;break;
33             }
34             sumd[k]=sumd[i]*sumd[prime[j]];
35             tmp1[k]=1+prime[j];tmp2[k]=prime[j];
36             mu[k]=-mu[i];
37         }
38     }
39     for(int i=1;i<=N;i++)p[i]=i;
40     sort(p+1,p+N+1,mt2);
41 }
42 unsigned int bit[N+10];
43 inline int lowbit(int a){return a&-a;}
44 inline void add(int pos,unsigned int val){while(pos<=N)bit[pos]+=val,pos+=lowbit(pos);}
45 inline unsigned int query(int pos)
46     {unsigned int ret=0;while(pos)ret+=bit[pos],pos-=lowbit(pos);return ret;}
47 inline unsigned int calc(unsigned int n,unsigned int m)
48 {
49     if(n>m)swap(n,m);
50     unsigned int ret=0,last;
51     for(unsigned int i=1;i<=n;i=last+1)
52     {
53         last=min(n/(n/i),m/(m/i));
54         ret+=(n/i)*(m/i)*(query(last)-query(i-1));
55     }
56     return ret;
57 }
58 int main()
59 {
60     intn();int top=1,t;scanf("%d",&t);
61     for(int i=1;i<=t;i++)
62         q[i].id=i,scanf("%d%d%d",&q[i].n,&q[i].m,&q[i].a);
63     sort(q+1,q+t+1,mt1);
64     for(int i=1;i<=t;i++)
65     {
66         while(top<=N&&sumd[p[top]]<=q[i].a)
67         {
68             for(int k=1;k*p[top]<=N;k++)
69                 add(k*p[top],mu[k]*sumd[p[top]]);
70             top++;
71         }
72         q[i].ans=calc(q[i].n,q[i].m);
73     }
74     sort(q+1,q+t+1,mt3);
75     for(int i=1;i<=t;i++)
76         printf("%d\n",q[i].ans&inf);
77 }
bzoj3529

相关文章:

猜你喜欢
  • 2022-02-22
  • 2022-12-23
  • 2021-12-08
  • 2021-08-04
  • 2022-01-07
  • 2021-10-08
相关资源
相似解决方案