题解 P4449 【于神之怒加强版】

teafrogsf

2018-04-19 23:40:31

Solution

~~被YMY先看到了这道题不开心。~~ ### 蒟蒻怒交BZOJRE代码,然后发现自己以前写数论题都打的啥~~还交了7遍~~...... 关于推式子这方面的东西仍然被楼下抢了~~而且大家套路怎么都一模一样~~,我这里只是说一下那个$N_k$应该是没有必要算的,因为你只会利用到它下标为质数的部分。~~以及一份在数学题里面基本上没有什么卵用的参考代码~~ ~~然后因为没卡常数并且全程$\rm long\ long$的原因速度比楼下低到不知道哪里去了。~~ $\rm int+1ll\vert(long\ long)$这种操作还是蛮好用的,尤其是在比赛的评测环境下可以跑得很快。大家可以学习一个~~虽然我没写~~。 ```cpp #include<cstdio> #define neko 5500010 #define chkmin(a,b) ((a)<(b)?(a):(b)) #define f(i,a,b) for(register int i=(a);i<=(b);i=-(~(i))) typedef long long ll; static ll n,m,k,ans,mod=1e9+7; static int cas; typedef long long arr[neko]; static arr isnprime,prime,F,sumF,Pow; template<typename T> void swap(T &a,T &b){T t=a;a=b,b=t;} static ll slowpow(ll m,ll n) { ll b=1; for(;n;n>>=1,m=m*m%mod)if(n&1)b=b*m%mod; return b; } inline void sieve() { F[1]=1,Pow[1]=1; f(i,2,5000010) { if(!isnprime[i])prime[++prime[0]]=i,F[i]=slowpow(i,k)-1,Pow[i]=F[i]+1; for(register int j=1;j<=prime[0]&&prime[j]*i<=5000010;j++) { isnprime[i*prime[j]]=1; // Pow[i*prime[j]]=Pow[i]*Pow[prime[j]]%mod; if(i%prime[j]==0){F[i*prime[j]]=F[i]*Pow[prime[j]]%mod;break;} F[i*prime[j]]=F[i]*F[prime[j]]%mod; } }f(i,1,5000010)sumF[i]=sumF[i-1]+F[i],sumF[i]%=mod; } int main() { int j; scanf("%d%lld",&cas,&k); sieve(); while(cas--) { scanf("%lld%lld",&n,&m); ans=0; if(n>m)swap(n,m); for(register int i=1;i<=n;i=j+1) { j=chkmin(n/(n/i),m/(m/i)); ans=(ans+(n/i)*(m/i)%mod*(sumF[j]-sumF[i-1])%mod)%mod; }printf("%lld\n",(ans+mod)%mod); }return 0; } ```