zju3547
题意:给出n(1<=n<=10^8),求小于n的,求所有与n互质的数字的四次幂的加和是多少。
分析:容斥原理
首先要知道四次幂求和公式,1^4+2^4+...+n^4=n*(n+1)*(2n+1)*(3n^2+3n-1)/30
先求所有小于等于n的数字的四次幂和,然后减去那些不互质的即可。
这个减去的过程用到了容斥原理。
先对n分解质因子,每个不同的质因子只保留一个。
然后分别枚举这些质因子的组合情况,由奇数个因子组成的数要减去,由偶数个因子组成的数要加上。
对于一个因子组合的乘积a,我们需要一次性计算a^4+(2a)^4 + (3a)^4+...
将其转化为a^4 * (1^4+2^4+...)即可。
这道题还有一个难点,就是公式中有除法(除以30),却还要进行模运算。
除法是不支持模运算的,因此我们要将除法转化为乘法,除以30变为乘以30的逆元。
逆元的意思是,如果a、b互为mod c下的逆元,则a * b = 1 (mod c)。
求逆元可以用扩展欧几里德gcd(30,MOD,x,y),把x/gcd(30,MOD)整理到0~MOD-1范围内即为30的逆元。
具体原因查阅扩展欧几里德算法。
#include <cstdio>
using namespace std; #define D(x) const int MOD = (int)(1e9) + ;
const int MAX_FACTOR = ; int n;
int factor_num;
long long factor[MAX_FACTOR];
long long inverse; //n(n+1)(2n+1)(3n^2+3n-1)/30 long long to_forth(long long value)
{
long long ret = value;
ret = ret * ret % MOD;
ret = ret * ret % MOD;
return ret;
} long long cal(long long value)
{
long long num = n / value;
long long ret = ;
ret = ret * num % MOD * (num + ) % MOD;
ret = ret * ( * num + ) % MOD;
ret = ret * ((num * num % MOD * % MOD + * num % MOD - ) % MOD) % MOD;
if (ret / != ret * inverse % MOD)
{
D(printf("#%lld %lld\n", ret / , ret * inverse % MOD));
}else
{
D(printf("**\n"));
}
ret = ret * inverse % MOD; ret = ret * to_forth(value) % MOD; return ret;
} void get_factors()
{
factor_num = ;
int m = n;
for (int i = ; i * i <= m; i++)
{
if (m % i == )
factor[factor_num++] = i;
while (m % i == )
{
m /= i;
}
}
if (m != )
{
factor[factor_num++] = m;
}
} long long work()
{
long long ans = ;
for (int i = ; i < ( << factor_num); i++)
{
int num = ;
long long temp = ;
int index = ;
for (int mask = ; mask <= i; mask <<= , index++)
{
if ((mask & i) == )
{
continue;
}
num++;
temp *= factor[index];
}
D(printf("temp=%lld\n", temp));
if (num & )
ans += cal(temp);
else
ans -= cal(temp);
ans = (ans % MOD + MOD) % MOD;
}
ans = ((cal() - ans) % MOD + MOD) % MOD;
return ans;
} void gcd_extend(long long a,long long b,long long &g,long long &x,long long &y)
{
if (!b)
{
g = a;
x = ;
y = ;
return;
}
gcd_extend(b, a % b, g, y, x);
y -= a / b * x;
} int main()
{
long long x, y, g;
gcd_extend(, MOD, g, x, y);
D(printf("%lld %lld %lld\n", x, y, g));
x = (x % MOD + MOD) % MOD;
inverse = x / g;
D(printf("%lld\n", inverse));
D(printf("%lld\n", inverse * % MOD));
int t;
scanf("%d", &t);
while (t--)
{
scanf("%d", &n);
if (n == )
{
puts("");
continue;
}
get_factors();
int ans_int = work();
printf("%d\n", ans_int);
}
return ;
}
zju3547的更多相关文章
随机推荐
- 初识ActionScript
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:fx="h ...
- MEF搜索范围
MEF对扩展组件的查找范围通常有三个: AssemblyCatalog:从某个程序集中查找. ApplicationCatalog:在应用程序所在的目录下查找. DirectoryCatalog:在某 ...
- TeX — Beauty and Fun
我是初学者,你推荐使用什么发行的 TeX? 我应该用 LaTeX 吗? 我认为最好的发行是 TeXLive CD,它不但包含了所有操作系统需要的程序,而且有许许多多宏包,如果你不是特别特殊的用户,有了 ...
- Java字节流:FilterInputStream FilterOutputStream
----------------------------------------------------------------------------------- FilterInputStrea ...
- 结果集(result set)解释与用法
解释: 引用自wiki: An SQL result set is a set of rows from a database, as well as metadata about the query ...
- RTX二次开发(二)(基于ASP.NET)
上一篇,我们讲到我开发环境的配置,还没配置好开发环境或再看一遍开发环境配置?接下来,我们开始coding...... 在coding之前,我们先添加引用. 我们在SDK的安装目录中引用这个文件. 引用 ...
- Eclipse 自动补全功能失效解决办法及修改快捷键方法
最近在学习Java,前段时间分盘把电脑能坏了,重装系统后发现我的Eclipse的自动补全的功能失效了,那多麻烦呀,什么都得自己打,于是百度后总结了以下解决方法: 1.点击Window-->Pre ...
- POJ 3744 Scout YYF I
分段的概率DP+矩阵快速幂 Scout YYF I Time Limit: 1000MS Memory Limit: 65536K Total Sub ...
- call() 和 apply() ----预定义的函数方法
- ajax异步提交数据动态更改select选项
<!DOCTYPE html> <html> <head> <title></title> <script src="../ ...