数论题
来源:互联网 发布:淘宝购物券网站 编辑:程序博客网 时间:2024/04/28 02:32
zoj1823
升序方式打印一个数(longlong范围)的所有素数因子
Sample Input
90
1234567891
18991325453139
12745267386521023
-1
Sample Output
2
3
3
5
1234567891
3
3
13
179
271
1381
2423
30971
411522630413
#include<stdio.h>#include<string>#include<string.h>#include<iostream>using namespace std;int main(){ long long n,i; while(cin>>n&&n>0) { i=2; while(1) { if(n%i==0)//这样保证除的一定是素数 { n/=i; printf("%lld\n",i); } else i++; if(i*i>n) { printf("%lld\n\n",n); break; } } } return 0;}
ZOJ1037 求n*m维矩阵最短路 从起点出发经过一次且仅一次,最后回到起点
#include<iostream>#include<cstdio>#include<algorithm>using namespace std;/* 规律:偶数行或偶数列必定存在全部为1的路径把所有点连起来 否则m行n列中存在 m*n-1个1 和 一个 sqrt(2) 的路径连起所有点*/int main(){int t;int k=1;cin>>t;while(t--){ int n,m;cin>>n>>m;printf("Scenario #%d:\n",k++);if(n%2==0||m%2==0)printf("%d.00\n",n*m);else printf("%.2lf\n",n*m-1+1.41);printf("\n");}return 0;}
ZOJ1049 求圆环半径 半圆的面积增量为50
r1*r1 - 0 = 100/pi
r2*r2 - r1*r1 = 100/pi
r3*r3 - r1*r1 = 100/pi
....
rn*rn - rn-1*rn-1=100/pi
故rn*rn=sqrt(100/pi)-sqrt(n) 循环一下即可
#include<cstdio>#include<cstdlib>#include<cstring>#include<cmath>#include<iostream>#define pi 3.1415926using namespace std;int main(){ int t; cin>>t; int k=1; while(t--) { double x,y,s,p,tt; cin>>x>>y; s=sqrt(x*x+y*y); int i=1; p=0; tt=sqrt(100/pi); while(i) { p=tt*sqrt(i); if(p>s){ printf("Property %d: This property will begin eroding in year %d.\n",k++,i); break; } i++; } } printf("END OF OUTPUT.\n"); return 0;}
或者 继续推导公式求解:
#include<cstdio>#include<cstdlib>#include<cstring>#include<cmath>#include<iostream>#define pi 3.1415926using namespace std;int main(){ int t; cin>>t; int k=1; while(t--) { double x,y,s,p; cin>>x>>y; s=sqrt(x*x+y*y); p=s/sqrt(100/pi); p=(int)(p*p+0.5); if(p==0)p=1; printf("Property %d: This property will begin eroding in year %.0lf.\n",k++,p); } printf("END OF OUTPUT.\n"); return 0;}
ZOJ1041
求半圆扫到的最多点数
用叉积求是否在直径两边即可,当在直线上时,两边都要算
#include<iostream>#include<cstdio>#include<cstring>#include<cmath>using namespace std;double px,py;struct ss{ double x,y;} data[200];int mul(int i,int j){ double x1,y1,x2,y2; x1=data[i].x-px; y1=data[i].y-py; x2=data[j].x-px; y2=data[j].y-py; double m=x1*y2-x2*y1; if(fabs(m)<0.000001)return 0; else if(m<0)return -1; else return 1;}int main(){ double r,a,b,m; while(cin>>px>>py>>r) { if(r<0)break; int n,k=0,i,j; cin>>n; while(n--) { cin>>a>>b; m=sqrt((px-a)*(px-a)+(py-b)*(py-b)); if(m<r||fabs(m-r)<0.0000001) { data[k].x=a; data[k].y=b; k++; } } int ma=0; for(i=0; i<k; i++) { int cnt1=0,cnt2=0; int f; for(j=0; j<k; j++) { f=mul(i,j); if(f==-1)cnt1++; else if(f==1)cnt2++; else { cnt1++; cnt2++; } } if(ma<cnt1)ma=cnt1; if(ma<cnt2)ma=cnt2; } printf("%d\n",ma); } return 0;}
计算时针与分针的夹角c(0<=c<=180) h(0,23) m(0,59)
double getc(int h,int m){ if(h>=12)h=h-12; h=h*60+m; double a1=1.0*h/2; double a2=1.0*m*6; double temp=(a1>a2?a1-a2:a2-a1); if(temp>=180)temp=360-temp; return temp;}
Description
Input
每行一个n(1<=n<=109)
Output
对于每个n输出最后亮着的灯的数量
Sample Input
Sample Output
找规律...
假设所有灯初始状态为0,操作后变为 100100001000000...;
即 1+2+4+1+6+1+8+1+10+....
#include<cstdio>#include<cmath>using namespace std;int main(){ int n,k; while(~scanf("%d",&n)) { int k=sqrt(n); while(k*k+2*k<n)k++; k--; int s=k+k*k; n=n-(k*k+2*k); if(n>=1)s+=n-1; printf("%d\n",s); }}
zoj2330
Solve the equation in the name of this problem.
Input
There are several cases. Each of them has a single real number as the smaller one of a and b in the equation on a separate line. You may assume it's no smaller than 1.1. Proceed until the end of file.
Output
For each case, print the other number on a single line. Keep 5 digits after decimal point. If no such number exists, print -1.
Sample Input
210
Sample Output
4.00000
-1
要注意到一句话:输入的是a和x中较小的那个,如果没有这句话的话就又是另一种做法了。我们可以对方程两边同时取对数,从而得到:ln(a)/a=ln(x)/x,移一下项得到f(x)=ln(a)/a-ln(x)/x,
求导可以计算得到1-ln(x),f(x)在(0,e)上单调递减,在(e,+无穷)上单调递增,当x=e的时候f(x)有最小值。
而且f(x)与x轴的两个交点就是所谓的可行解a和b
那么我们很显然的可以得到a和b分列于e的两边。
既然a是较小的那个,那么必然有a<e
故,当a已经大于了e就必然无解,这个时候输出-1
反之一定有解。
于是可以二分计算出答案。
注意到x>e的那个部分是单调递增的。
#include<stdio.h>#include<math.h>#define E exp(1.0f)//自然对数int main(){ double a; while(scanf("%lf",&a)!=-1) { if(a>E) { printf("-1\n"); } else { double l=E,r=44.0; double mid=44.0; bool flag=false; while(l<=r) { mid=(l+r)/2.0; //printf("mid=%.5lf\n",mid); double temp1=log(a)/a; double temp2=log(mid)/mid; if(temp1<temp2) { l=mid+0.000001; } else if(temp1>temp2) r=mid-0.000001; else break; } printf("%.5lf\n",mid); } } return 0;}
ZOJ3498找规律
题目分析
二分法,每次将不小于n/2个javabeans的盒子拿出n/2个javabeans,
然后规模就小了一半,一直进行此操作,知道所有盒子的球为0为止
此题也就是求n的二进制的位数
#include<cstdio>#include<iostream>using namespace std;int main(){ int t,n; cin>>t; while(t--) { cin>>n; int s=0; while(n) { n/=2; s++; } cout<<s<<endl; } return 0;}
ZOJ1871 找规律
差值 排列
1 1
2 1 1
4 1 2 1
6 1 2 2 1
9 1 2 3 2 1
12 1 2 3 3 2 1
16 1 2 3 4 3 2 1
20 1 2 3 4 4 3 2 1
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<cmath>#define N 100using namespace std;int main(){ int n,m,len; while(cin>>n>>m) { len=m-n; int sum=0,step=0; if(len==0){ printf("0\n"); continue; } for(int i=1;;i++) { sum+=i; step++; if(sum>=len) { printf("%d\n",step); break; } sum+=i; step++; if(sum>=len) { printf("%d\n",step); break; } } } return 0;}
Description
有一条长度为n的绳子,想要把这条绳子切成尽可能多的段,并且每段的长度必须为大于等于1的整数而且任意三段绳子都不能组成三角形。请问最多能切几段?
Input
测试文件的第一行有一个正整数T,代表一共有T组测试数据。
每组测试数据的第一行为一个正整数n(1<=n<=100000000)。
Output
对于每组测试数据,输出对应的答案。
Sample Input
Sample Output
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;int main(){ int t,i; int f[45]; f[0]=f[1]=1; for(i=2;i<45;i++)f[i]=f[i-1]+f[i-2]; cin>>t; while(t--) { int n; cin>>n; for(i=0;i<45;i++) { n-=f[i]; if(n<0)break; } printf("%d\n",i); } return 0;}
1466: Lucky Boy
Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 19 Solved: 6
[Submit][Status][Web Board]
Description
Recently, Lur have a good luck. He is also the cleverest boy in his school as he create the most popular computer game – Lucky Boy. The game is played by two players, a and b, in 2d planar .In the game Lucky Boy, there are n different points on plane, each time one can remove one or multiple co-line points from the plane. The one who can firstly remove more than two points from the plane wins. The one who removes the last point on the plane can also win the game. You may assume that two players are both clever enough that they can always make the best choice. The winner is called Lucky Boy. Given the n points, can you tell me who will be the Lucky Boy ? Note that player a will always the first one to remove points from the plane.
Input
The first line of each case is an integer n(0<n<=103), following n lines each contains two integers x and y(0<=x, y<=108), describing the coordinates of each point. Ended by EOF.
Output
Output “a is the lucky boy.” in a single line if a win the game, otherwise you should output “b is the lucky boy.” in a single line.
Sample Input
Sample Output
HINT
先判断是不是三点共线 让后博弈
#include<iostream>#include<cstdio>#include<algorithm>#include<vector>#include<string>#include<cmath>#include<map>#include<cstring>#define N 1010using namespace std;struct ss{ double x,y;}a[N],res[N*N];map<double,int>q;int main(){ int n,i,j,k; while(~scanf("%d",&n)) { q.clear(); for(i=0;i<n;i++)scanf("%d%d",&a[i].x,&a[i].y); if(n<3){ printf("a is the lucky boy.\n"); continue; } int flag=0; int num=0; for(i=0;i<n;i++) { for(j=i+1;j<n;j++) { if(a[j].x-a[i].x==0)continue; double tmp=(a[j].y-a[i].y)/(a[j].x-a[i].x); res[num].x=i; res[num].y=j; int t=q[tmp]; if(q[tmp]&&(i==res[t].x||i==res[t].y||j==res[t].x||j==res[j].y)){ flag=1; break; } else q[tmp]=num; num++; } if(flag)break; } if(flag)printf("a is the lucky boy.\n"); else { if(n%3)printf("a is the lucky boy.\n"); else printf("b is the lucky boy.\n"); } } return 0;}
ZOJ
打表得出一部分Magic Number:
2
5
10
20
25
50
100
125
200
250
500
1000
1250
2000
2500
5000
10000
12500
20000
25000
50000
100000
125000
200000
250000
500000
1000000
1250000
2000000
2500000
5000000
10000000
12500000
20000000
25000000
50000000
100000000
Process returned 0 (0x0) execution time : 12.393 s
Press any key to continue.
然后就好做了
#include<iostream>#include<cstdio>using namespace std;int main(){ long long a[100]={1,2,5,10,20,25,50}; long long p=1; int i; for(i=7;i<90;) { a[i++]=100*p; a[i++]=125*p; a[i++]=200*p; a[i++]=250*p; a[i++]=500*p; p*=10; } //for(i=0;i<100;i++)printf("%d %lld\n",i+1,a[i]); int x,y; while(~scanf("%d%d",&x,&y)) { int s=0; for(i=0;i<90;i++) { if(a[i]>y)break; if(a[i]>=x&&a[i]<=y)s++; } printf("%d\n",s); } return 0;}
ZOJ1133
水题,本题讲的是判断一个数(排除素数)的各个数位之和是否等于将它分解成质数相乘形式时,各个数位之和
学会了怎样快速求质因子,
#include<cstdio>#include<cstring>#include<cmath>#include<iostream>#include<vector>using namespace std;vector<int>pri,fac;int get(int n){ int s=0;; while(n) { s+=n%10; n/=10; } return s;}int factor(int n){ fac.clear(); int i=0; int num=n; for(i=0;pri[i]<=n&&i<pri.size();i++) { while(n>=pri[i]&&n%pri[i]==0){ n/=pri[i]; fac.push_back(pri[i]); } } if(n!=1)fac.push_back(n); /* printf("fac: "); for(i=0;i<fac.size();i++)printf("%d ",fac[i]); printf("\n"); */ if(fac[0]==num)return -1; else{ int s=0; for(i=0;i<fac.size();i++)s+=get(fac[i]); return s; }}void inti(){ pri.clear(); int i,j; for(i=2;i<10010;i++)//测试数据 sqrt(N)<10010 { for(j=2;j<=sqrt(i);j++)if(i%j==0)break; if(j>sqrt(i))pri.push_back(i); } // for(i=0;i<pri.size();i++)printf("%d\n",pri[i]);}int main(){ int n,i; inti(); while(~scanf("%d",&n)&&n) { while(n++) { int x=get(n); int y=factor(n); // printf("** %d %d\n",x,y); // getchar(); if(x==y) { printf("%d\n",n); break; } } } return 0;}
ZOJ3716
题意:给你四个点,四个人在四个点上舞动丝带,各条丝带不能相遇,求四人最大的丝带总长度,即求最大的半径和。。
#include<cstdio>#include<cstring>#include<cmath>#include<vector>#include<iostream>#include<algorithm>using namespace std;double x[5],y[5];double dis(double x1,double y1,double x2,double y2){ return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));//相乘结果超出int范围,所以数据类型都用double}int main(){ while(~scanf("%lf%lf",&x[0],&y[0])) { int i; for(i=1;i<4;i++)scanf("%lf%lf",&x[i],&y[i]); double d1=dis(x[0],y[0],x[1],y[1]); double d2=dis(x[0],y[0],x[2],y[2]); double d3=dis(x[0],y[0],x[3],y[3]); double d4=dis(x[1],y[1],x[2],y[2]); double d5=dis(x[1],y[1],x[3],y[3]); double d6=dis(x[2],y[2],x[3],y[3]); double ans=min(d1+d6,min(d2+d5,d3+d4)); printf("%.8lf\n",ans); } return 0;}
zoj3785
思路:
打表i的i次方%7后的值,就可以发现42一循环
然后用公式计算出结果
最后输出即可
4、AC代码:
- #include<stdio.h>
- int s[45];
- char str[7][10]={"Saturday","Sunday","Monday","Tuesday","Wednesday","Thursday","Friday"};
- int main()
- {
- s[0]=0;
- for(int i=1;i<=44;i++)
- {
- int flag=i%7;
- int ans=1;
- for(int j=1;j<=i;j++)
- ans=(ans*flag)%7;
- s[i]=ans;
- }
- for(int i=1;i<=44;i++)
- {s[i]+=s[i-1];}
- int t;
- while(scanf("%d",&t)!=EOF)
- while(t--)
- {
- int n;
- scanf("%d",&n);
- int ans=(n/42%7*(s[42]%7)%7+s[n%42]%7)%7;
- printf("%s\n",str[ans]);
- }
- }
通过打表发现周期是294,那么就简单了
- #include <stdio.h>
- #include <string.h>
- #include <algorithm>
- using namespace std;
- char day[10][10] = {"Saturday","Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday"};
- int s[300];
- int work(int n)
- {
- int sum = 1,i;
- for(i = 1;i<=n;i++)
- {
- sum = sum*n;
- sum%=7;
- }
- return sum;
- }
- int main()
- {
- int t,n,i,j,len;
- s[0] = 0;
- for(i = 1;i<=294;i++)
- {
- s[i] = s[i-1]+work(i);
- s[i]%=7;
- }
- scanf("%d",&t);
- while(t--)
- {
- scanf("%d",&n);
- n%=294;
- printf("%s\n",day[s[n]]);
- }
- return 0;
- }
hdu4920 Matrix multiplication 模3矩阵乘法
hdu4920
Matrix multiplication
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others) Total Submission(s): 568 Accepted Submission(s): 225bobo hates big integers. So you are only asked to find the result modulo 3.
The first line contains n (1≤n≤800). Each of the following n lines contain n integers -- the description of the matrix A. The j-th integer in the i-th line equals Aij. The next n lines describe the matrix B in similar format (0≤Aij,Bij≤109).
Print n lines. Each of them contain n integers -- the matrix A×B in similar format.
2014多校5的最水的题,我没做出来,怕了。
题意:给出两个n*n的矩阵A和B,求A*B结果矩阵,元素都模3,n<=800。
题解:矩阵乘法加剪枝(?)。
800*800的矩阵,多组数据,直接算是会超时得飞起来的,只有考虑模3的特殊性。
读入后每个元素模3,得到的矩阵里全是0,1,2,随机数据的话有三分之一是零,所以我们的矩阵乘法要用k i j的循环嵌套顺序,第二层里面发现A[i][k]==0时就continue,直接少一维,也就是1/3概率少一维。这个是这题最关键的一步,没想到这步的话,其他再怎么优化也没用(我们试过了……)。
另外运算时可以使用cal[i][j][k]提前计算好((i*j)+k)%3,矩阵乘法的时候直接用这个结果。
------------------------------其他------------------------------------
顺便说个笑话:为什么Dijkstra没发明Floyd算法?因为他是ijk不是kij……
比赛的时候我们做这题优化得飞起来,读入输出优化,gets按字符串读一行来处理,输出用putchar,乘法、取余运算用上面说的那步省掉,输出不用'0'+C[i][j]而用数组存好ch[0]='0'这样输出,就差用fread一次读多行了……可是就是TLE,因为我们没想到最关键那步……
代码:
#include<cstdio>#include<cmath>#include<iostream>#include<cstring>#include<algorithm>#include<cmath>#include<map>#include<set>#include<stack>#include<queue>using namespace std;#define ll __int64#define usint unsigned int#define mz(array) memset(array, 0, sizeof(array))#define minf(array) memset(array, 0x3f, sizeof(array))#define REP(i,n) for(int i=0;i<(n);i++)#define FOR(i,x,n) for(int i=(x);i<=(n);i++)#define RD(x) scanf("%d",&x)#define RD2(x,y) scanf("%d%d",&x,&y)#define RD3(x,y,z) scanf("%d%d%d",&x,&y,&z)#define WN(x) printf("%d\n",x);#define RE freopen("D.in","r",stdin)#define WE freopen("1.out","w",stdout)int n;const int maxn=800;int A[maxn][maxn],B[maxn][maxn],C[maxn][maxn];int cal[3][3][3];int main() { int i,j,k; for(i=0; i<3; i++) for(j=0; j<3; j++) for(k=0; k<3; k++) cal[i][j][k]=((i*j)+k)%3; while(scanf("%d",&n)!=EOF) { for(i=0; i<n; i++) for(j=0; j<n; j++) { scanf("%d",&A[i][j]); A[i][j]%=3; } for(i=0; i<n; i++) for(j=0; j<n; j++) { scanf("%d",&B[i][j]); B[i][j]%=3; } mz(C); for(k=0; k<n; k++) for(i=0; i<n; i++) { if(A[i][k]==0)continue;///这个是关键!模3有三分之一是零,也就有三分之一概率去一维,碉! for(j=0; j<n; j++) { ///re.a[i][j]=(re.a[i][j]+(A.a[i][k]*B.a[k][j])); C[i][j]=cal[A[i][k]][B[k][j]][C[i][j]]; } } for(i=0; i<n; i++) { for(j=0; j<n-1; j++) { putchar(C[i][j]+'0'); putchar(' '); } putchar(C[i][n-1]+'0'); puts(""); } } return 0;}
- 数论题
- Ones数论题zju1889
- FZU 1607 数论题
- 悲剧的数论题
- 杭电 数论题
- POJ 数论题集
- POJ 数论题集
- 一些数论题
- hdu1395(简单数论题)
- ACM数论题集
- 数论题大集合
- ACM数论题集
- 数论题集
- 数论题大集合
- hdu1299(数论题)
- 数论题集
- 数论题4例
- 数论题 (牛客网)
- Android开源项目第三篇——优秀项目篇
- tomcatpluginv33 下载
- JM参数详解
- 层次短语模型学习笔记
- 25个增强iOS应用程序性能的提示和技巧
- 数论题
- spring 基础特性--转滴--比较通俗易懂
- 有价证券之T+n
- Search in Rotated Sorted Array
- ImageView的属性android:scaleType,即ImageView.setScaleType(ImageView.ScaleType)
- STDOUT/STDERR重定向到ALOG中
- 产品防伪码查询系统_学历学籍查询系统_证书查询系统_录取成绩查询系统_工资查询系统_信息查询系统
- Android开源项目第四篇——开发及测试工具篇
- 【Icon测试】Icon Strike帮你在主屏幕上快速测试iOS icon设计