题目
题意:
对于一个数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; }