您的位置:首页 > 其它

2017.10.9 DZY Loves Math V 失败总结

2017-10-09 21:17 239 查看
这种题是不是有什么套路啊。。反正这个系列的题一道都不会。。

据说这个系列是鏼爷出的。。%%%ORZORZ

这个phi似乎很多题都用了他积性函数的性质。。都是分素数分素数,统计统计,,然后加着加着就变成乘了。。

由于不同素数的影响是独立的。。所以可以用乘法原理

所以ans=第一个素数的贡献*第二个素数的贡献*....

统计一个素数的贡献时每一个ai拆出的素数情况也是独立的,,所以    一个素数的贡献=a1拆的贡献*a2拆的贡献+a3拆的贡献+...

单个a的贡献就是一组累乘了。。。(如果不直观的话可以把所有数都拆成几个1来表示组合关系,,然后发现一组里的1是可以合并的,答案不变)

由于ai==1e7  所以多次出现的素数一定<sqrt(1e7)

剩下的还有出现一次的,单独统计即可

码(又丑又慢):

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define ll long long
#define P 1000000007
ll n,p[100005],he[10000005],ans=1,i,j,k,geshu,ni,su[10000005],tot,a[100005];
ll ksm(ll a,ll b)
{
ll ans=1;
while(b)
{
if(b%2)ans=(ans*a)%P;
b/=2;
a=(a*a)%P;
}
return ans;
}
void eular(ll n)
{
ll i,j;
for(i=2;i<=n;i++)
{
if(!he[i])
{
su[++tot]=i;
}
for(j=1;j<=tot&&su[j]*i<=n;j++)
{
he[su[j]*i]=1;
if(i%su[j]==0)
{
break;
}
}
}
}
int main()
{
scanf("%lld",&n);
eular(5000);
for(i=1;i<=n;i++)scanf("%lld",&a[i]);
for(i=1;i<=tot;i++)
{//cout<<i<<" "<<tot<<" ";
ll o=su[i];
ll lin=1;
p[0]=1;
he[0]=1;
ni=ksm(o,P-2);
for(j=1;j<=30;j++)
{
p[j]=(p[j-1]*o)%P;
he[j]=(he[j-1]+p[j])%P;
}
for(j=1;j<=n;j++)
{
geshu=0;
while(a[j]%o==0)
{
a[j]/=o;
geshu++;
}
lin=lin*he[geshu]%P;
}
if(lin>1)ans=(ans*((lin-1)%P*(o-1)%P*ni%P+1))%P;
}
tot=0;
memset(he,0,sizeof(he));
for(i=1;i<=n;i++)
{
if(a[i]>1)
{
if(he[a[i]]==0)su[++tot]=a[i];
he[a[i]]++;
}
}
for(i=1;i<=tot;i++)
{
ans=ans*((ksm(su[i]+1,he[su[i]])-1)*(su[i]-1)%P*ksm(su[i],P-2)%P+1)%P;
}
printf("%lld",ans);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: