几道数学题
2014-05-13 20:52
330 查看
从给定的[a,b]区间选出一个数x,从[c,d]区间选出数y,问有多少对(x,y)满足(x+y)%p=m
思路:对于a<=x<=b,c<=y<=d.满足条件的结果为ans=f(b,d)-f(b,c-1)-f(a-1,d)+f(a-1,c-1)。
而函数f(a,b)是计算0<=x<=a,0<=y<=b满足条件的结果。这样计算就很方便了。
LLgcd(LLx,LLy){
returny==0?x:gcd(y,x%y);
}
LLp,m;
LLans(LLa,LLb){
if(a<
0||b<0)return0;
LLs=0;
LLma=a%p,mb=b%p;
s+=(a/p)*(b/p)*p;
s+=(ma+1)*(b/p)+(mb+1)*(a/p);
if(ma>m){
s+=min(m,mb)+1;
LLt=(p+m-ma)%p;
if(t<=mb)s+=mb-t+1;
}
else{
LLt=(p+m-ma)%p;
if(t<=mb)s+=min(mb-t+1,m-t+1);
}
returns;
}
intmain(){
intt,T=
1;
LLa,b,c,d,s,g,f;
cin>>t;
while(t--){
cin>>a>>b>>c>>d>>p>>m;
s=ans(b,d)-ans(c-1,b)-ans(a-1,d)+ans(a-1,c-1);
f=(d-c+1)*(b-a+1);
g=gcd(f,s);
printf("Case#%d:%I64d/%I64d\n",T++,s/g,f/g);
}
return
0;
}
路径f:由A到D;g:由B到C的路径。沿坐标轴正方向走,f,g不能有交集。求路径对(f,g)总数
A(0,0),B(p,0),C(m,q),D(m,n);因为(f,g)不相交数=(f,g)总数-(f,g)相交数;
总数:c(m+n,m)*c(m-p+q,q);
相交数:c(m+q,m)*c(m-p+n,n);
constLLmod=100000007;
LLexgcd(LLa,LLb,LL&x,LL&y){
if(b==0){
x=1;
y=0;
returna;
}
LLg=exgcd(b,a%b,x,y);
LLt=x;
x=y;
y=t-(a/b)*y;
returng;
}
LLinverse(LLn){
LLx,y;
exgcd(n,mod,x,y);
return(x%mod+mod)%mod;
}
LLC(LLn,LLm){
LLu=1,v=1;
for(LLi=0;i<m;i++){
u=u*(n-i)%mod;
v=v*(i+1)%mod;
}
returnu*inverse(v)%mod;
}
intmain(){
LLs,m,n,p,q;
while(cin>>m>>n>>p>>q){
s=C(m+n,n)*C(m+q-p,q)%mod;
s-=C(m+q,m)*C(m+n-p,n)%mod;
s=(s%mod+mod)%mod;
cout<<s<<endl;
}
return0;
}
要求满足的m=a^3+b^3=(a+b)(a2-ab+b2)的(a,b)组合。
令t=x1+x2,则t一定是m的约数,所以应枚举m的所有约数。然后可以得到
t=x1+x2
n/t=x1^2-x1*x2+x2^2;
=t*t–3x1*x2
ðx1*x2=(t*t-n/t)/3=m;
有韦达定理x1,x2为二次方程x^2–mx+t=0的2正整数根
再就是注意范围要用unsignedlonglong。
typedefunsignedlonglongll;
constllM=3000001;
intcnt,num,cn;
llprime[M],p[100],e[100];
boolf[M];
lln;
voidmake(){
cnt=0;
for(inti=2;i<M;i++){
if(!f[i])prime[cnt++]=i;
for(intj=0;j<cnt&&i*prime[j]<M;j++){
f[i*prime[j]]=1;
if(i%prime[j]==0)break;
}
}
}
voidfac(llm){
num=0;
for(lli=0;i<cnt&&(ll)prime[i]*prime[i]<=m;i++){
if(m%prime[i]==0){
p[num]=prime[i];
llj=1;
m/=prime[i];
while(m%prime[i]==0){
j++;
m/=prime[i];
}
e[num++]=j;
}
}
if(m>1){
p[num]=m;
e[num++]=1;
}
}
llispw2(lla){
llb=sqrt(1.0*a);
if((ll)b*b==a)returnb;
returnM;
}
map<ll,ll>answer;
map<ll,ll>::iteratorit;
voidis(llt){
llx1,x2;
llp=n/t;
lla=t*t-p;
if(a>0&&a%3!=0)return;
llm=a/3;
llb=t*t-4*m;
if(b<0)return;
llc=ispw2(b);
if(c==M)return;
if((t+c)%2==0){
x1=(t+c)/2;
x2=t-x1;
if(x1>x2)swap(x1,x2);
if(x1>0&&x1<t&&x2>0&&x2<t&&answer.find(x1)==answer.end()){
answer[x1]=x2;
}
}
}
llPow(llx,lly){
lls=1;
for(;y;y>>=1,x*=x){
if(y&1)s*=x;
}
returns;
}
voiddfs(intid,lls){
is(s);
if(id>=num)return;
for(inti=0;i<=e[id];i++)
dfs(id+1,(ll)s*Pow(p[id],i));
}
intmain(){
make();
while(scanf("%llu",&n)!=EOF){
fac(n);
cn=0;
answer.clear();
dfs(0,1);
printf("%d",answer.size());
for(it=answer.begin();it!=answer.end();it++)
printf("(%llu,%llu)",it->first,it->second);
printf("\n");
}
return0;
}
一门课的书有N章内容要复习,每天可以复习一章,但是有M个限制条件:在第D[i]天中无法复习第C[i]章,问不同的复习方案数
容斥原理,不考虑约束条件,则一共有N!种复习方案,然后减去刚好触发一个约束条件的方案数,加上刚好触发两个约束条件的方案数,减去刚好触发三个的……依此类推另外注意一点,输入中可能包含重复的约束条件,要先去重再算容斥,否则会得到错误的结果
题意抽象出来就是在n*n的棋盘中加了m个禁位,放置n个棋子,每两个棋子不在同一行同一列,问有多少中放置方式?
trick:
M个禁位中有相同坐标的点。
解法:利用有禁位的排列的公式(容斥原理):
n!-r1*(n-1)!+r2*(n-2)!-r3*(n-3)!+..........
ri指在禁区中选i个位置的方案数。
由于m的值较小,可直接dfs暴力求方案数。
constLLmod=55566677;
intx[28],y[28];
LLp[60];
boolvisx[60],visy[60];
intn,m;
LLs;
voiddfs(intcnt,intid,intf){
s=(s+p[n-cnt]*f)%mod;
s=(s+mod)%mod;
for(inti=id+1;i<m;i++){
if(!visx[x[i]]&&!visy[y[i]]){
visx[x[i]]=visy[y[i]]=1;
dfs(cnt+1,i,-f);
visx[x[i]]=visy[y[i]]=0;
}
}
}
intmain(){
inti,j;
p[0]=p[1]=1;
for(i=2;i<60;i++)p[i]=p[i-1]*i%mod;
while(cin>>n>>m){
for(i=0;i<m;i++)scanf("%d%d",&x[i],&y[i]);
for(i=0;i<m;i++){
for(j=i+1;j<m;j++){
if(x[i]==x[j]&&y[i]==y[j]){
swap(x[j],x[m-1]);
swap(y[j],y[--m]);
}
}
}
memset(visx,0,sizeof(visx));
memset(visy,0,sizeof(visy));
s=0;
for(i=0;i<m;i++){
visx[x[i]]=visy[y[i]]=1;
dfs(1,i,1);
visx[x[i]]=visy[y[i]]=0;
}
s=(p
-s)%mod;
s=(s+mod)%mod;
cout<<s<<endl;
}
return0;
}
限位排列
一门课的书有N章内容要复习,每天可以复习一章,但是第i章不能在第i天或第i+1天复习(最后一章则对应最后一天和第一天),问不同的复习方案数,
递推公式如下:
intmain(){
f[0]=f[3]=1,f[1]=f[2]=0,f[4]=2;
intn;
for(n=5;n<=maxn;n++){
if(n%2)
f
=(f[n-1]*n%mod+(f[n-2]*n%mod+4)*inverse(n-2))%mod;
else
f
=(f[n-1]*n%mod+(f[n-2]*n%mod-4)*inverse(n-2))%mod;
}
while(scanf("%d",&n)!=EOF){
printf("%lld\n",f
);
}
return0;
}
题意:求第k个斐波那契素数对应的斐波那契数列及其之后的值%x==0的最小的斐波那契数值,(%m),
zoj
数据范围:(1<=k<=10^6),(3<=X<=100),(10<=M<=10^6)
解题思路:
斐波那契数列的特性:(0,1,1,2,3,5,8...)
1、gcd(fib(n),fib(m))=fib(gcd(n,m))
2、如果fib(k)能被x整除,则fib(k*i)都可以被x整除。
3、f(0)+f(1)+f(2)+…+f(n)=f(n+2)-1
4、f(1)+f(3)+f(5)+…+f(2n-1)=f(2n)
5、f(2)+f(4)+f(6)+…+f(2n)=f(2n+1)-1
6、[f(0)]^2+[f(1)]^2+…+[f(n)]^2=f(n)·f(n+1)
7、f(0)-f(1)+f(2)-…+(-1)^n·f(n)=(-1)^n·[f(n+1)-f(n)]+1
8、f(m+n)=f(m-1)·f(n-1)+f(m)·f(n)
9、[f(n)]^2=(-1)^(n-1)+f(n-1)·f(n+1)
10、f(2n-1)=[f(n)]^2-[f(n-2)]^2
11、3f(n)=f(n+2)+f(n-2)
12、f(2n-2m-2)[f(2n)+f(2n+2)]=f(2m+2)+f(4n-2m)[n〉m≥-1,且n≥1]
还有一个结论:
计算(a/b)%c其中b能整除a
如果b与c互素,则(a/b)%c=a*b^(phi(c)-1)%c
如果b与c不互素,则(a/b)%c=(a%bc)/b
对于b与c互素和不互素都有(a/b)%c=(a%bc)/b成立
斐波那契素数的定义:(2,3,5,13,89...)
对于斐波那契数列的第i个元素s[i],如果gcd(s[i],s[j])==1(1<=j<i),那么s[i]是一个斐波那契素数。
斐波那契素数的特性(可根据斐波那契数列求出斐波那契素数):
对于斐波那契数列(0,1,1,2,3,5,8...),下标从0开始,下标为3,4,5,7,11,13...的数就是斐波那契素数。
即除了前两个外,斐波那契数列的素数下标对应的就是斐波那契素数,而如果下标不是素数,那么对应的也不是斐波那契素数。
所以这一题就先筛出斐波那契素数下标(3,4,5,7,11,13...),然后就可以知道第k个斐波那契素数对应的斐波那契数列的下标,
根据矩阵快速幂计算出斐波那契数值,判断是否%x==0,如果不是就继续找下一个,直到找到为止。最后a/x%m=(a%(x*m))/x
typedeflonglongLL;
constintmaxn=15500000;
intprimesize;
intprime[maxn+8];
boolis[maxn+8];
voidmake(){
primesize=0;
memset(is,0,sizeof(is));
for(inti=2;i<=maxn;i++){
if(!is[i])prime[++primesize]=i;
for(intj=1;j<=primesize&&prime[j]*i<=maxn;j++){
is[prime[j]*i]=1;
if(i%prime[j]==0)break;
}
}
prime[1]=3;
prime[2]=4;
}
LLmod;
structMat{
LLx[3][3];
Mat(){
x[1][1]=0,x[1][2]=0;
x[2][1]=0,x[2][2]=0;
}
Mat(int){
x[1][1]=1,x[1][2]=0;
x[2][1]=0,x[2][2]=1;
}
Mat(LLa11,LLa12,LLa21,LLa22){
x[1][1]=a11,x[1][2]=a12;
x[2][1]=a21,x[2][2]=a22;
}
};
Matoperator*(MatA,MatB){
Mats;
for(inti=1;i<=2;i++){
for(intj=1;j<=2;j++){
for(intk=1;k<=2;k++){
s.x[i][j]+=A.x[i][k]*B.x[k][j];
s.x[i][j]%=mod;
}
}
}
returns;
}
Matoperator^(Matx,inty){
Mats(1);
for(;y;y>>=1){
if(y&1)s=s*x;
x=x*x;
}
returns;
}
constMatF(1,1,1,0);
intmain(){
make();
LLk,x,m;
inti,t;
MatA;
cin>>t;
while(t--){
scanf("%lld%lld%lld",&k,&x,&m);
intid=prime[k];
mod=x;
for(i=id;;i++){
A=F^(i-1);
if(A.x[1][1]%x==0)break;
}
mod=x*m;
A=F^(i-1);
printf("%lld\n",A.x[1][1]/x);
}
return0;
}
关于方程a^x=1(modm)的最小x解
定理:设gcd(a,m)=1,必有正整数x,使得a^x=1(modm),且设满足等式的最小正整数为x0,必满足x0|phi(m).注意m>1.
否则如果gcd(a,m)!=1,则方程a^x=1(modm)没有解。
constintmaxn=70000;
intprime[maxn];
intprimesize;
boolis[maxn+10];
voidmake(){
memset(is,0,sizeof(is));
primesize=0;
for(inti=2;i<=maxn;i++){
if(!is[i])prime[primesize++]=i;
for(intj=0;j<primesize&&i*prime[j]<=maxn;j++){
is[i*prime[j]]=1;
if(i%prime[j]==0)break;
}
}
}
intphi(intn){
intm=sqrt(0.5+n);
ints=n;
for(inti=0;i<primesize&&n!=1&&prime[i]<=m;i++){
if(n%prime[i]==0){
s=s-s/prime[i];
while(n%prime[i]==0)n/=prime[i];
}
}
if(n!=1)s=s-s/n;
returns;
}
intgcd(intx,inty){
returny==0?x:gcd(y,x%y);
}
structFac{
intx;
ints;
Fac(){}
Fac(int_x,int_s):x(_x),s(_s){}
}h[208];
vector<int>factor;
vector<int>::iteratorit;
intfacsize;
voidgetfac(intn){
intm=sqrt(0.5+n),t;
facsize=0;
for(inti=0;i<primesize&&n!=1&&prime[i]<=m;i++){
if(n%prime[i]==0){
t=0;
while(n%prime[i]==0){t++;n/=prime[i];}
h[facsize++]=Fac(prime[i],t);
}
}
if(n!=1)h[facsize++]=Fac(n,1);
}
intPow(intx,inty){
ints=1;
for(;y;y>>=1,x*=x){
if(y&1)s*=x;
}
returns;
}
intPow(intx,inty,intm){
ints=1;
for(;y;y>>=1,x*=x,x%=m){
if(y&1)s*=x,s%=m;
}
returns;
}
voiddfs(intid,intn){
if(id==facsize){
factor.push_back(n);return;
}
for(inti=0;i<=h[id].s;i++)
dfs(id+1,n*Pow(h[id].x,i));
}
voidgetfactor(intn){
factor.clear();
getfac(n);
dfs(0,1);
sort(factor.begin(),factor.end());
}
intanswer(inta,intm){
getfactor(phi(m));
for(it=factor.begin();it!=factor.end();it++){
if(Pow(a,*it,m)==1)return*it;
}
}
intmain(){
make();
intn,i,ph;
while(scanf("%d",&n)!=EOF){
if(n==1||gcd(2,n)!=1){
printf("2^?mod%d=1\n",n);
continue;
}
printf("2^%dmod%d=1\n",answer(2,n),n);
}
return0;
}
写法2
LLphi(LLn){
LLs=n;
LLm=(LL)sqrt(0.5+n);
for(LLi=2;n!=1&&i<=m;i++){
if(n%i==0){
s=s-s/i;
while(n%i==0)n/=i;
}
}
if(n!=1)s=s-s/n;
returns;
}
LLgcd(LLx,LLy){
returny==0?x:gcd(y,x%y);
}
vector<LL>factor;
vector<LL>::iteratorit;
voidgetfactor(LLn){
factor.clear();
LLm=(LL)sqrt(0.5+n);
for(LLi=1;i<=m;i++){
if(n%i==0){
factor.push_back(i);
if(i*i!=n)factor.push_back(n/i);
}
}
sort(factor.begin(),factor.end());
}
LLPow(LLx,LLy,LLm){
LLs=1;
for(;y;y>>=1,x*=x,x%=m){
if(y&1)s*=x,s%=m;
}
returns;
}
LLanswer(LLa,LLm){
getfactor(phi(m));
for(it=factor.begin();it!=factor.end();it++){
if(Pow(a,*it,m)==1)return*it;
}
}
intmain(){
LLn,i;
while(scanf("%I64d",&n)!=EOF){
if(n==1||gcd(2,n)!=1){
printf("2^?mod%lld=1\n",n);
continue;
}
printf("2^%I64dmod%I64d=1\n",answer(2,n),n);
}
return0;
}
题目大意是:在一个平面上有N个点,每个点的坐标已经给出,现在要求在X轴上找一个点,使得这个点到所有点中最大的距离最小。
分析:我们设这个点为X0,所求的距离为F(x),那么对于所有的X<X0和X>X0都有F(x)>ans,即实际上这个函数是已X0为最小值,两边
都是单调递增或者递减的,因此我们可以三分查找找出这个最值的坐标。总复杂度O(n*logn).
constdoubleEPS=1e-9;
constintmaxn=50008;
intn;
doublex[maxn],y[maxn];
doublef(doublenx){
doubles=0,d;
for(inti=1;i<=n;i++){
d=sqrt(y[i]*y[i]+(x[i]-nx)*(x[i]-nx));
if(s<d)s=d;
}
returns;
}
//三分对凹(凸)函数判断最小(大)值,此题是求最小值。
//不要求左l右r值的大小比较,即(L<R或L>=R)都可
doubletri_search(doublel,doubler){
doubleMid,Midmid,L,R;
L=l;
R=r;
while(L+EPS<R){//由于L,R没有要求谁大谁小,故求的绝对值
Mid=(L+R)*0.5;
Midmid=(Mid+R)*0.5;
if(f(Mid)<=f(Midmid))
R=Midmid;
else
L=Mid;
}
return(L+R)*0.5;
}
intmain(){
inti;
doublel,r,nx;
while(cin>>n&&n){
l=200008;
r=-200008;
for(i=1;i<=n;i++){
scanf("%lf%lf",&x[i],&y[i]);
l=min(l,x[i]);
r=max(r,x[i]);
}
nx=tri_search(l,r);
printf("%.9lf%.9lf\n",nx,f(nx));
}
return0;
}
相关文章推荐
- 类型转换
- opengl shader 入门 超详细
- POJ 1236 Network of Schools 强连通
- 引用返回左值
- SpringMVC 避免IE执行AJAX时,返回JSON出现下载文件
- Silverlight 预定义颜色速查表
- opencv 滤波
- 网络流+二分构图
- MESI协议
- leetcode difficulty and frequency distribution chart
- 点分治专题——bzoj 1468 &bzoj 2152 题解
- Git操作基本命令
- poj 3624 Charm Bracelet(01背包)
- 九度 OJ 1004 median
- 【Java编程】建立一个简单的JDBC连接-Drivers, Connection, Statement and PreparedStatement
- C#l里的位移符号
- cocos2d-x 动作的分类与使用
- ubuntu12.04 virtualbox xp 识别usb
- struts2配置国际化全局资源文件 并 输出国际化信息
- MFC中Combo Box 的用法总结