2017.9.22 模拟考试 解题报告
2017-09-22 20:24
176 查看
2017.9.22 模拟考试 解题报告
T1
T1写写看看,一会就发现规律了,然后,除法分块,徐队说:“开莫比乌斯函数,sigma什么的一定会考除法分块”,这道题在洛谷上就叫 约数和#include<iostream> #include<cstring> #include<cstdio> using namespace std; #define LL long long inline LL calc(int n){ LL l=1,r,a,ret=0; for(;l<=n;l=r+1){ a=n/l;//l,r 是区间的左右端点 a代表连续的等差的序列的被用次数 r=n/a; ret+=(r-l+1)*(r+l)*0.5*a; } return ret; } int main(){ freopen("A.in","r",stdin); freopen("A.out","w",stdout); int x,y; cin>>x>>y; cout<<calc(y)-calc(x-1); fclose(stdin);fclose(stdout); return 0; }
等差序列求和公式
Sn=(a1+an)*n*0.5;
再详细说明一下a含义
举个栗子:
X=1,Y=12,Ans=sigma f(i)
1 2 3 4 5 6 7 8 9 10 11 12
12 6 4 3 2 2 1 1 1 1 1 1
第一个等差数列是l=1,r=1,a=12,意思就是说1作为因数贡献了12次
5、6下面对应都是2
5、10、6、12
该等差数列用了两次,恩,应该说的很明白了,当i越大的时候等差数列的长度越长,效率越高。
T2
UVa11440 原题思路:ϕ(m!)表示小于m!并与m!互质的个数,而与m!互质的个数,他的质因子肯定不包含1-m,因此就是满足条件的。然后对于这题而言,则是要求n!中,不与m!互质的个数,答案取模100000007
求kn中与n互质的个数,答案为kϕ(n)。
ϕ(n)表示1-n中与n互质的个数,那么由此考虑[n + 1, 2n], [2n + 1, 3n]…这每个区间中的每个数字都等于1-n中数字加上kn,对于原来就与n不互质的个数,加上n仍会有一个质因子重复,所以仍然不行,那么对于原来互质的数x,gcd(x, n) = 1,那么可知gcd(x + kn, n) = 1,仍然是互质的,所以每隔n的区间与n互质的个数是相同的,所以答案kϕ(n)
所以对于这道题目,答案就变成了n!/m!ϕ(m!),那么问题只剩下如何求ϕ(m!)。
m!=1*2*3*….*m 所以对m!的阶乘质因数分解得到的因子只能是1-m中的质数。
已知ϕ(n)求法为n∗(1−1/p1)∗(1−1/p2)….(1−1/pn) (p为n的质因子),因此对于m!而言,分子为m!,分母为1 - m所有质数的(1−1/p)之乘积
到这里答案就可以求了,把m!消掉,得到n!/∏(1−1/pi)mod1000000007,先预处理那些表,每次去计算即可
#include<cstdio> using namespace std; #define MAXN 10000001 #define Mod 100000007 #define LL long long int prime[664580],cnt; bool v[MAXN]; LL phifac[MAXN]; int main(){ freopen("B.in","r",stdin); freopen("B.out","w",stdout); int n,m; scanf("%d%d",&n,&m); for(int i=2;i<MAXN;++i){ if(!v[i]) prime[++cnt]=i; for(int j=1;j<=cnt;++j){ if(i*prime[j]>=MAXN) break; v[i*prime[j]]=true; if(i%prime[j]==0) break; } } LL ans=0; phifac[1]=1; for(int i=2;i<=m;++i) if(!v[i]) phifac[i]=phifac[i-1]*(i-1)%Mod; else phifac[i]=phifac[i-1]*i%Mod; ans=phifac[m];//现在ans就是phi(m!) for(register int i=m+1;i<=n;++i) ans=ans*i%Mod; //Ans乘上n!/m!倍 printf("%I64d\n",ans-1); return 0; }
上篇代码注释:phifac[m]表示m!的欧拉函数值
解释一下我的递推式:
最原始的方程phi((m-1)!)=(m-1)!((P1-1)/P1) ….((Pk-1)/Pk)
当m是质数时,phi(m!)= m*(m-1)! ((P1-1)/P1) ….((Pk-1)/Pk)((m-1)/m),中间那一块就是phi((m-1)!),==> phi(m!)= m*phi((m-1)!)((m-1)/m),两个蓝色的m再约个分,就得了上面代码里的样子了
当m不是质数的时候,phi(m!)= m*(m-1)! ((P1-1)/P1) ….((Pk-1)/Pk),【因为m不是质数嘛,m肯定可以用p1、p2、、、、pk中的几个质因子表示】,然后中间一坨还是phi((m-1)!),于是乎又有了上面代码中的样子。。
T3
UVa6396 原题网上有好几份题解是反素数,看了看没看懂,还是看徐队的搜索吧。
#include<iostream> #include<cstring> #include<cstdio> using namespace std; #define LL long long int prime[25]={0,2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71}; LL ans,n,C[70][70]; void solve(int num,int lim,LL tot,LL now,int last){ if(now>ans) return ; if(tot==n) { ans=now; return ; } if(tot>n || num>20) return ; LL t=1; for(int i=1;i<=lim;++i){ t*=prime[num]; if(now>=ans/t) return; solve(num+1,i,tot*C[last+i][i],now*t,last+i); } } int main(){ freopen("C.in","r",stdin); freopen("C.out","w",stdout); C[0][0]=1; for(int i=1;i<70;++i){ C[i][0]=1; for(int j=1;j<=i;++j) C[i][j]=C[i-1][j]+C[i-1][j-1]; } scanf("%I64d",&n); if(n==1) { printf("1 2\n"); return 0; } ans=(LL)1<<60; solve(1,63,1,1,0); printf("%I64d\n",ans); return 0; }
这道题当时在考场上退出了反着做的正解,哈哈哈,没什么软用。
从最小的质数开始枚举选几个
假设前i-1个种质数用了k个,有Np种方案,第i种质数选a个,
那么前i种质数的方案就有Np*C[k+a][a]
可以理解原来有k个位置,又加了a个位置,有a个数可以放在任意位置
所以前i种的每一种方案都变成C[k+a][a]种
枚举每个质数选几个时,如果上一个质数选了k个,那么这一个质数最多选k个
假设这个质数选了k+1个,那么显然上一个质数选k+1个,这个选k个更优,就是说大质数陪小底数,小大,大小。
相关文章推荐
- 【九度】2014年王道论坛计算机考研机试全真模拟考试解题报告
- [USACO Jan07]考试Schul解题报告
- 2015年秋季大学先修课考试 解题报告
- 7.18 DP考试解题报告
- 洛谷 1928 外星密码 模拟? 解题报告
- jzoj 1568. 【普及模拟】石子游戏 解题报告
- 【总结】10.25.2017 考试总结与解题报告
- NOIP模拟2017.6.11解题报告
- JZOJ.4300[NOIP2015模拟11.3]装饰大楼 解题报告
- JZOJ.4465[GDOI2016模拟4.22] 飞机调度 解题报告
- 2018.1.21【POJ - 2260】解题报告(模拟,图论引申)
- PAT 银行排队问题之单窗口“夹塞”版 (队列+模拟) -- 解题报告
- 7.3模拟比赛解题报告
- LuoguP1572 计算分数 解题报告【模拟】
- CCF 201609-2 火车购票 解题报告 简单模拟
- jzoj 1569. 【普及模拟】公共子串 解题报告
- codevs 1191 数轴染色 模拟? 解题报告
- jzoj 1347. 【2011.12.17普及模拟】晚餐队列安排 解题报告
- JZOJ.3431【GDOI2014模拟】网格 解题报告
- JZOJ.3432【GDOI2014模拟】服务器 解题报告