题意:找出{0 ,1,……,n - 1}这个集合中的子集的元素的和能整除n的个数。
思路:不会推导,打了个表,还是没发现规律,找到网站才发现规律为:a(n) = 1/n * sum_{d divides n and d is odd}2^(n/d) * phi(d).
哎,都不好意思粘了。。
#include<bits/stdc++.h>
using namespace std;
const int Mod = 1e9 + 7;
typedef long long ll;
const int maxn = 1e6 + 10;
ll pow_mod(ll x,ll n)
{
ll ret = 1;
while(n)
{
if(n & 1)
ret = ret * x % Mod;
n >>= 1;
x = x * x % Mod;
}
return ret;
}
ll euler[maxn];
void Init()
{
euler[1] = 1;
for(int i = 2; i < maxn; i ++)
euler[i] = i;
for(int i = 2; i <= maxn; i ++)
{
if(euler[i] == i)
for(int j = i; j < maxn; j += i)
euler[j] = euler[j]/i * (i - 1);
}
}
ll phi(ll n)
{
ll ans = n;
for(int i = 2; i * i <= n; i ++)
{
if(n % i == 0)
{
ans = ans / i * (i - 1);
while(n % i == 0)
n /= i;
}
}
if(n > 1)
ans = ans / n * (n - 1);
return ans;
}
ll phis(ll x)
{
return x < maxn ? euler[x] : phi(x);
}
ll n;
int main()
{
Init();
int Tcase;
scanf("%d",&Tcase);
while(Tcase --)
{
scanf("%I64d",&n);
ll ans = 0;
ll rev = pow_mod(n,Mod - 2);
// cout << rev << endl;
for(int i = 1; i * i <= n; i ++)
{
if(n % i == 0)
{
int d = i;
if(d % 2 == 1)
ans += pow_mod(2,n/d) * phis(d) % Mod,
ans %= Mod;
if(n != i * i && (n / d) % 2 == 1)
ans += pow_mod(2,d) * phis(n/d)% Mod,
ans %= Mod;
}
}
printf("%I64d\n",ans * rev % Mod);
}
return 0;
}