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的更多相关文章
随机推荐
- 我的J2EE学习历程
由于最近手头没有JSP项目,所以暂停Hibernate和Spring的研究.个人觉得只有发现某个东西的不足之后再去学习新的东西来弥补这个不足比较好.就好比,最开始在JSP页面里面写Java代码,每次操 ...
- SignalR 资料
链接:http://www.cnblogs.com/royding/p/3919134.html
- angularjs之自己定义指令篇
1>指令基础知识 directive() 参考资料 http://www.tuicool.com/articles/aAveEj http://damoqiongqiu.iteye.com/bl ...
- 【转载】 C中的access函数
分类: C/C++ int access(const char *filename, int amode); amode参数为0时表示检查文件的存在性,如果文件存在,返回0,不存在 ...
- linux脚本编程(shell)浅介 (转载)
linux脚本(shell)编程 啊,昨天上网看到一篇讲 linux/unix shell 的文章,想想自己最后写这东西也是一年前的事了,想想都快忘光了. 还是整理一下,做一次回顾,以后说不定还用得上 ...
- Java字节流:BufferedInputStream BufferedOutputStream
-----------------------------------------------------------------------------------BufferedInputStre ...
- C/C++/Java/C#语言的基本类型
C语言的基本类型有:char, short ,int ,long ,float ,double 一共6种基本类型. C++语言有:bool, char ,wchar_t, short, int , l ...
- GetDlgItem
GetDlgItem是父窗口用来获取它的子窗口的句柄的. 如果是在一个对话框里想要获取另一个对话框中元素的句柄,假设B对话框的指针为pWnd,则pCtrl = pWnd->GetDlgItem( ...
- dubbo框架----探索-大型系统架构设计(图解)
对于高并发系统的架构要求: 1. 负载均衡 2.高并发 3.高可用 4.面向服务架构 (Dubbo框架使用) 5.分布式缓存 (redis分布式缓存) 6.分布式全文检索 (solr分分布式全文检索) ...
- 大熊君大话NodeJS之------Http模块
一,开篇分析 首先“Http”这个概念大家应该比较熟悉了,它不是基于特定语言的,是一个通用的应用层协议,不同语言有不同的实现细节,但是万变不离其宗,思想是相同的, NodeJS作为一个宿主运行环境,以 ...