题目链接:https://ac.nowcoder.com/acm/problem/19836
Problem
给出一个数轴,刚开始人在位置0,有n个变量,每一个变量的值范围是[1,m],每次人可以选择其中一个变量,假设值为d,那么他可以向左或向右走d个单位长度,为最终在位置1的概率。
Solution
其实就是.
根据裴蜀定理可知这个方程有整数解的条件是.
有因为1<=ai<=m,所有得出公式:
由于m太大,所有先用杜教筛求出莫比乌斯函数的前缀和,m/d用数论分块求。
Code
#include <bits/stdc++.h>
#define ll unsigned long long
#define pir pair<int,int>
#define debug(x) cout << #x << ":" << x << '\n'
const int N = 1e7+7;
const ll mod = 1e9+7;
const ll ds = 1e15;
const double eps = 1e-8;
using namespace std;
ll prime[N],phi[N],mu[N];
map<long long,ll>mp;
int cnt = 0;
void init(){
mu[1] = 1;
for(int i = 2; i <= N; i++){
if(!phi[i]){
prime[cnt++] = i;
phi[i] = i-1;
mu[i] = -1;
}
for(int j = 0; j < cnt && i*prime[j] <= N; j++){
if(i%prime[j] == 0){
phi[i*prime[j]] = phi[i]*prime[j];
break;
}
else {
phi[i*prime[j]] = phi[i]*phi[prime[j]];
mu[i*prime[j]] = -mu[i];
}
}
}
for(int i = 1; i <= N; i++){
mu[i] += mu[i-1];
}
}
ll djsmu(ll x){//杜教筛
if(x < N) return mu[x];
if(mp.count(x)) return mp[x];
ll ans = 1;
for(ll l = 2,r; l <= x; l = r+1){
r = x/(x/l);
ans -= (r-l+1)*djsmu(x/l);
}
return mp[x] = ans;
}
ll qpow(ll x,ll y){
ll res = 1;
while(y){
if(y&1) res = res*x;
y >>= 1;
x = x*x;
}
return res;
}
void solve(){
init();
ll n,m,ans = 0;
cin >> n >> m;
for(ll l = 1,r; l <= m; l = r+1){
r = m/(m/l);
ans = (ans+(qpow(m/l,n)*(djsmu(r)-djsmu(l-1))));
}
//ans = (ans*qpow(m,n))%mod;
cout << ans << endl;
}
int main(){
// int t;
// cin >> t;
// while(t--)
solve();
system("pause");
return 0;
}