题意:
对于一个数n,有一些这样的一个数对(p,q),满足1<=p<=q<=n,且lcm(p,q)=n。则f(n)等于所有的这样的数对的p和q的和。已知n(以底数和指数的形式给出),求f(n)。
题解:
考虑底数pi,对应指数ai,若p的指数小于ai,则q的指数必等于ai;若p的指数等于ai,则q的指数无所谓。通过枚举p每个底数的指数,可知q有多少种取法(可能会导致p>q,没关系)。加起来就可以。
但是直接枚举p的每一个取值会TLE。显然p的指数小于ai时q的方案数是相同的,所以可以一起算。
到最后除了(n,n)只算了一次外,每个数对都算了两次,所以加上2*n后再除2就是答案。
有些数据不预处理出乎意料地慢,要注意。
//Time:316ms
//Memory:0KB
//Length:1362B
#include <iostream>
#include <cstdio>
#include <cstdlib>
using namespace std;
#define MAXN 1010
#define MOD 1000000007
int p[MAXN],a[MAXN],c,mnum[MAXN],db[MAXN][2];
long long ans;
int pow_mod(long long a,int po)
{
long long ret=1;
while(po)
{
if(po&1) ret=ret*a%MOD;
po>>=1,a=a*a%MOD;
}
return ret;
}
inline int caldb(int a,int b)
{
return (long long)(pow_mod(a,b)-1)*pow_mod(a-1,MOD-2)%MOD;
}
void dfs(int h,long long now,long long now2,long long fan1,long long fan2)
{
for(int i=h;i<c;++i)
{
dfs(i+1,now*db[i][0]%MOD,now2*mnum[i]%MOD,fan1,fan2*a[i]%MOD);
now=now*mnum[i]%MOD,now2=now2*db[i][1]%MOD,fan1=fan1*(1+a[i])%MOD;
}
ans=(ans+now*fan1%MOD+now2*fan2%MOD)%MOD;
}
int main()
{
//freopen("/home/moor/Code/input","r",stdin);
int ncase,two=pow_mod(2,MOD-2);
scanf("%d",&ncase);
for(int hh=1;hh<=ncase;++hh)
{
scanf("%d",&c);
ans=0;
for(int i=0;i<c;++i)
{
scanf("%d%d",&p[i],&a[i]);
mnum[i]=pow_mod(p[i],a[i]);
db[i][0]=caldb(p[i],a[i]);
db[i][1]=caldb(p[i],a[i]+1);
}
dfs(0,1,1,1,1);
long long tmp=1;
for(int i=0;i<c;++i) tmp=tmp*mnum[i]%MOD;
ans=(ans+tmp*2%MOD)*two%MOD;
printf("Case %d: %d\n",hh,(int)ans);
}
return 0;
}