2017.9.5 DZY Loves Math 失败总结

来源:互联网 发布:社区门诊软件 编辑:程序博客网 时间:2024/06/06 15:55

真是神(du)题

首先,利用公式和套路可以化成这样:


然后就不会了、


题解就比较神了

设g(k)=Σ[k|T]*mu[T/k]*f[k]

大概思想就是T中的每一种次数  都  和k相差不过1 ,不然就是0

然后就是选择一个和选择0个的区别;;

选择奇数个和选择偶数个的方案*f是一样的   (好吧,这个不会证)

然后就用线筛筛g就可以了、

有空想清楚了在写点吧


码(仿制品)

#include<iostream>#include<cstdio>#define ll long long#define N 10000005   using namespace std;int n,m,a[N],tot,b[N],su[N],g[N],j;void eular(int n){int i;for(i=2;i<=n;i++){if(!a[i]){   su[++tot]=i;           g[i]=1;   a[i]=1;//最小  质因子次数    b[i]=i;//最小   质因子几次方 }for(j=1;su[j]*i<=n&&j<=tot;j++){int k=su[j]*i;if(i%su[j])//i不含第j个质数 {                    //得到新的最小次数    a[k]=1;       //这两个数相乘 最小次数是1    b[k]=su[j];   //所以更新次方                 g[k]=(a[i]==1)?-g[i]:0;  //如果i的最小也是1,就取反、、 }else{   //如果含有          a[k]=a[i]+1;      //次数+1          b[k]=b[i]*su[j];   //乘上 int lin=i/b[i];   //   if (lin==1) g[k]=1; else g[k]=(a[lin]==a[k])?-g[lin]:0;//如果它是次方,就是1  其他就判断一下    break; }}}  for (i=2; i<=10000000; i++) g[i]+=g[i-1];  }int main(){ int T; scanf("%d",&T);  eular(10000000);    while (T--){          scanf("%d%d",&m,&n); int i,j; ll ans=0;          for (i=1; i<=m && i<=n; i=j+1){  //根n枚举             j=min((m/(m/i)),n/(n/i));              ans+=(ll)(g[j]-g[i-1])*(m/i)*(n/i);  //统计答案         }          printf("%lld\n",ans);      }  }