题目链接:点击这里
题目大意:
题目分析:
好久以前的代码,发现一直
waiting
\text{waiting}
waiting 就
rejudge
\text{rejudge}
rejudge 了一下,然后
ac
\text{ac}
ac 了,特此记录一下
具体细节见代码:
//#pragma GCC optimize(2)
//#pragma GCC optimize("Ofast","inline","-ffast-math")
//#pragma GCC target("avx,sse2,sse3,sse4,mmx")
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<set>
#include<map>
#include<stack>
#include<queue>
#define ll long long
#define inf 0x3f3f3f3f
#define int unsigned ll
#define endl '\n'
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
using namespace std;
int read()
{
int res = 0,flag = 1;
char ch = getchar();
while(ch<'0' || ch>'9')
{
if(ch == '-') flag = -1;
ch = getchar();
}
while(ch>='0' && ch<='9')
{
res = (res<<3)+(res<<1)+(ch^48);//res*10+ch-'0';
ch = getchar();
}
return res*flag;
}
const int maxn = 1e6+5;
//const int mod = 1e9+7;
const double pi = acos(-1);
const double eps = 1e-8;
int n,m ,cnt,pri[maxn],sp1[maxn],sp2[maxn],sq;
int w[maxn],tot,id1[maxn],id2[maxn],g[maxn];
bool vis[maxn];
void get_pri(int n)
{
for(int i = 2;i <= n;i++)
{
if(!vis[i])
{
pri[++cnt] = i;
sp1[cnt] = (sp1[cnt-1]+i);
sp2[cnt] = (sp2[cnt-1]+i*i);
}
for(int j = 1;j <= cnt && i*pri[j] <= n;j++)
{
vis[i*pri[j]] = true;
if(i%pri[j] == 0) break;
}
}
}
int qpow(int a,int b)
{
int res = 1;
while(b)
{
if(b&1) res = res*a;
a = a*a;
b >>= 1;
}
return res;
}
ll S(int i,int j)
{
if(pri[j] >= i) return 0;
ll pos = i<=sq ? id1[i] : id2[n/i];
ll res = g[pos]-j*(m+1); //质数部分贡献
for(int k = j+1;k<=cnt && pri[k]*pri[k]<=i;k++) //合数部分贡献
{
ll pe = pri[k];
for(int e = 1;pe <= i;e++,pe = pe*pri[k]) //不能取模
{
ll x = pe;
res = (res+(m*e+1)*(S(i/pe,k)+(e>1)));
}
}
return res;
}
signed main()
{
get_pri(1e6);
int t = read();
while(t--)
{
tot = 0;
n = read(); m = read(); sq = sqrt(n);
for(int l = 1,r;l <= n;l = r+1)
{
r = min(n,n/(n/l));
w[++tot] = n/l; //取余方便计算下述的g(n,0)
g[tot] = w[tot]-1;
if(w[tot] <= sq) id1[w[tot]] = tot;
else id2[n/w[tot]] = tot;
}
for(int j = 1;j <= cnt;j++) //g(n,j)
for(int i = 1;i<=tot && pri[j]*pri[j]<=w[i];i++)
{
ll tmp = w[i]/pri[j];
ll pos = tmp <= sq ? id1[tmp] : id2[n/tmp];
g[i] = g[i]-g[pos]+j-1;
}
for(int i = 1;i <= tot;i++) g[i] *= (m+1);
printf("%llu\n",(S(n,0)+1));
}
return 0;
}