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.1415926
using 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.1415926
using 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 100
using 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 1010
using 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矩陣乘法
Matrix multiplicationTime Limit: 4000/2000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others) Total Submission(s): 568 Accepted Submission(s): 225Problem Description
Given two matrices A and B of size n×n, find the product of them.
bobo hates big integers. So you are only asked to find the result modulo 3. Input
The input consists of several tests. For each tests:
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). Output
For each tests:
Print n lines. Each of them contain n integers -- the matrix A×B in similar format. Sample Input
1 0 1 2 0 1 2 3 4 5 6 7
Sample Output
0 0 1 2 1
Author
Xiaoxu Guo (ftiasch)
Source
Recommend
|
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;
}