洛谷 P2155 BZOJ 2186 codevs 2301 [SDOI2008]沙拉公主的困惑
题目描述
大富翁国因为通货膨胀,以及假钞泛滥,政府决定推出一项新的政策:现有钞票编号范围为1到N的阶乘,但是,政府只发行编号与M!互质的钞票。房地产第一大户沙拉公主决定预测一下大富翁国现在所有真钞票的数量。现在,请你帮助沙拉公主解决这个问题,由于可能张数非常大,你只需计算出对R取模后的答案即可。R是一个质数。//codevs这里有坑,R是合数
输入输出格式
输入格式:
第一行为两个整数T,R。R<=10^9+10,T<=10000,表示该组中测试数据数目,R为模 后面T行,每行一对整数N,M,见题目描述 m<=n
输出格式:
共T行,对于每一对N,M,输出1至N!中与M!素质的数的数量对R取模后的值
输入输出样例
1 11
4 2
1 数据范围:
对于100%的数据,1 < = N , M < = 10000000
解题思路
http://www.cnblogs.com/yangyaojia/p/6434611.html、
http://blog.csdn.net/loi_dqs/article/details/50520309
吐槽
这题一题能抵三题做了。
不想被卡常就离线吧,筛法筛到最大的n即可,否则卡常、卡内存太严重了,我的好不容易洛谷ac,跑了6s。
求逆元可以线性递推,也可以扩欧。
popoqqq大神博客的代码(https://www.luogu.org/record/show?rid=2565704)、黄学长博客(https://www.luogu.org/record/show?rid=2565713)里线性递推逆元的代码都在洛谷爆零,不知为啥。
我的代码离线int会溢出,估计是筛法出问题,还不够优化,于是递推求逆元的数组开不下了,就用扩欧吧。
卡一波常1.3s跑完(BZOJ不开O2跑了2.9s)。
源代码
6s的,求逆元用线性递推(BZOJ TLE)
#include<cstdio>
#include<cstring>
#include<algorithm>
int T,R,n,m;
long long jc[]={};//阶乘取模
long long inv[]={};//逆元
bool not_prime[]={};//筛子
long long ans[]={};//pi累乘 void init()
{
inv[]=;
for(int i=;i<=&&i<R;i++)
inv[i]=(R-R/i)%R*inv[R%i]%R;
ans[]=;jc[]=;
for(int i=;i<=;i++)
{
jc[i]=jc[i-]*i%R;
if(!not_prime[i])
{
ans[i]=ans[i-]*(i-)%R*inv[i%R]%R;
for(int j=i<<;j<=;j+=i)
not_prime[j]=;
}
else
ans[i]=ans[i-];
}
} int main()
{
scanf("%d%d",&T,&R);
init();
while(T--)
{
scanf("%d%d",&n,&m);
printf("%lld\n",(long long)(jc[n])*(long long)(ans[m])%R);
}
return ;
}
1.3s的,求逆元用扩欧
#include<cstdio>
#include<algorithm>
int T,R,maxn=-;
long long jc[]={};//阶乘取模
//int inv[10000010]={0};//逆元
bool not_prime[]={};//筛子
long long ans[]={};//pi累乘
int n[]={},m[]={}; void exgcd(int a,int b,int &x,int &y)
{
if(b==){x=;y=;return;}
exgcd(b,a%b,x,y);
int t=x;x=y;y=t-a/b*y;
}
inline int getine(int t)
{
int x,y;
exgcd(t,R,x,y);
return (x%R+R)%R;
}//扩欧求逆元 inline void Read(int &in){
static char ch;
for(ch=getchar();ch>''||ch<'';ch=getchar()) ;
for(in=;ch>=''&&ch<='';ch=getchar()) in=in*+ch-'';
}
void init()
{
/*inv[1]=1;
for(int i=2;i<=maxn&&i<R;i++)
inv[i]=(R-R/i)%R*inv[R%i]%R;*///线性递推求逆元
ans[]=;jc[]=;
for(int i=;i<=maxn;i++)
{
jc[i]=jc[i-]*i%R;
if(!not_prime[i])
{
ans[i]=ans[i-]*(i-)%R*getine(i%R)%R;
for(int j=i<<;j<=maxn;j+=i)
not_prime[j]=;
}
else
ans[i]=ans[i-];
}
} int main()
{
Read(T);Read(R);
for(register int i=;i<=T;i++)
Read(n[i]),Read(m[i]),maxn=std::max(maxn,n[i]);
init();
for(register int i=;i<=T;i++)
printf("%lld\n",jc[n[i]]*ans[m[i]]%R);
return ;
}
洛谷记录里最优的代码,用户ID小小莫。Orz,洛谷跑了0.9s,BZOJ不开O2跑了2.6s,素数筛法值得学习。
#include <cstdio>
#include <algorithm>
using namespace std;
static const int maxm = + ;
static const int maxx = + ;
typedef long long LL;
bool Notprime[maxx];
int inv[maxx],phi[maxx],fac[maxx],prime[maxx];
int T,n[maxm],m[maxm],p,cnt,tot; void Read(int &); inline void Linear_shaker(){
int maxn = tot+;
fac[]=;inv[]=;phi[]=;
for(register int i=;i<maxn;i++){
if(!Notprime[i])
prime[++cnt]=i;
for(register int j=;j<=cnt && i*prime[j]<maxn;j++){
Notprime[i*prime[j]]=;
if(i%prime[j]==) break;
}
}
for(register int i=;i<=maxn;i++){
fac[i] = ((LL)fac[i-]*i)%p;
if(i<p) inv[i] = (LL)(p-p/i)*inv[p%i]%p;
if(!Notprime[i]) phi[i] = (LL)phi[i-]*(i-)%p*inv[i%p]%p;
else phi[i] = phi[i-];
}
}
int main(){
Read(T),Read(p);
for(register int i=;i<=T;i++) Read(n[i]),Read(m[i]),tot = max(tot,n[i]);
Linear_shaker();
for(register int i=;i<=T;i++)
printf("%lld\n",(LL)fac[n[i]]*phi[m[i]]%p);
return ;
} void Read(int &in){
static char ch;
for(ch=getchar();ch>''||ch<'';ch=getchar()) ;
for(in=;ch>=''&&ch<='';ch=getchar()) in=in*+ch-'';
}
洛谷 P2155 BZOJ 2186 codevs 2301 [SDOI2008]沙拉公主的困惑的更多相关文章
- 洛谷 P2155 [SDOI2008]沙拉公主的困惑 解题报告
P2155 [SDOI2008]沙拉公主的困惑 题目描述 大富翁国因为通货膨胀,以及假钞泛滥,政府决定推出一项新的政策:现有钞票编号范围为\(1\)到\(N\)的阶乘,但是,政府只发行编号与\(M!\ ...
- 洛咕 P2155 [SDOI2008]沙拉公主的困惑
洛咕 P2155 [SDOI2008]沙拉公主的困惑 有个结论,就是如果\(gcd(a,b)=1\),那么\(gcd(a+kb,b)=1\).证明比较显然. 所以这个题目要问的\(n!\)就可以分成\ ...
- Bzoj 2186: [Sdoi2008]沙拉公主的困惑 乘法逆元,线性筛,欧拉函数,数论
2186: [Sdoi2008]沙拉公主的困惑 Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 2560 Solved: 857[Submit][St ...
- 数学(逆元):BZOJ 2186: [Sdoi2008]沙拉公主的困惑
2186: [Sdoi2008]沙拉公主的困惑 Description 大富翁国因为通货膨胀,以及假钞泛滥,政府决定推出一项新的政策:现有钞票编号范围为1到N的阶乘,但是,政府只发行编号与M!互质的钞 ...
- 【BZOJ 2186】 2186: [Sdoi2008]沙拉公主的困惑 (欧拉筛,线性求逆元)
2186: [Sdoi2008]沙拉公主的困惑 Description 大富翁国因为通货膨胀,以及假钞泛滥,政府决定推出一项新的政策:现有钞票编号范围为1到N的阶乘,但是,政府只发行编号与M!互质的钞 ...
- 【bzoj2186】[Sdoi2008]沙拉公主的困惑
2186: [Sdoi2008]沙拉公主的困惑 Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 3303 Solved: 1129[Submit][S ...
- BZOJ2186: [Sdoi2008]沙拉公主的困惑(求[1,N!]与M!互素的个数)(线性筛)
2186: [Sdoi2008]沙拉公主的困惑 Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 6103 Solved: 2060[Submit][S ...
- BZOJ2186 [Sdoi2008]沙拉公主的困惑 【数论,欧拉函数,线性筛,乘法逆元】
2186: [Sdoi2008]沙拉公主的困惑 Time Limit: 10 Sec Memory Limit: 259 MB Submit: 5003 Solved: 1725 [Submit] ...
- 【BZOJ2186】[Sdoi2008]沙拉公主的困惑 线性筛素数
[BZOJ2186][Sdoi2008]沙拉公主的困惑 Description 大富翁国因为通货膨胀,以及假钞泛滥,政府决定推出一项新的政策:现有钞票编号范围为1到N的阶乘,但是,政府只发行编号与M! ...
随机推荐
- 53. 部门信息显示 EXTJS 单击树节点
1. /** * @author sux * @time 2011-1-14 * @desc 部门信息显示 */ deptInfoGridPanel = Ext.extend(Ext.grid.Edi ...
- 【TODO】Ruby Range类
创建: 2017/10/28 Range类 ...
- [Swift通天遁地]二、表格表单-(16)在表单行内嵌入日期和时间拾取器
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号:山青咏芝(shanqingyongzhi)➤博客园地址:山青咏芝(https://www.cnblogs. ...
- 自学Python十二 战斗吧Scrapy!
初窥Scrapy Scrapy是一个为了爬取网站数据,提取结构性数据而编写的应用框架. 可以应用在包括数据挖掘,信息处理或存储历史数据等一系列的程序中. 还是先推荐几个学习的教程:Scrapy 0.2 ...
- js基础---数字日期及运算
显示年月日 var a=new Date; console.log(a); var year=a.getFullYear(); var month=a.getMonth()+1; var day=a. ...
- UDP网络程序实例
根据前面所讲的网络编程的基础知识,以及UDP网络编程的特点,下面创建一个广播数据报程序.广播数据报是一种较新的技术,类似于电台广播,广播电台需要在指定的波段和频率上广播信息,收听者也要将收音机调到指定 ...
- [Windows Server 2012] PHPWind安全设置
★ 欢迎来到[护卫神·V课堂],网站地址:http://v.huweishen.com★[护卫神·V课堂]是护卫神旗下专业提供服务器教学视频的网站,每周更新视频. ★ 本节我们将带领大家:PHPWin ...
- WCF开发的流程-服务端和客户端之间的通讯(内含demo讲解)
讲解技术之前,恳请博友让我说几句废话.今天是我第一在博客园发布属于自己原创的博文(如有雷同,那是绝对不可能的事,嘿嘿).之前一直是拜读各位博友的大作,受益匪浅的我在这对博友们说声谢谢,谢谢你们的共享! ...
- eclipse的任务列表
如上图所示,备注加 TODO ,可以在tasks列表中显示,提示你还有哪些工作需要完善 昨天遇到一个问题,加了 TODO 任务列表里却不显示,后来发现是因为任务列表只显示了前100条,而我的项 ...
- SweetAlert弹出框
以前也用过,那个时候没有写过,突然看见了,就写上了. 网址:http://mishengqiang.com/sweetalert2/ swal({ title: '确定删除吗?', text: '你将 ...