數論題

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

有一個屋裏有n盞燈,燈的編號1,2,3,4。。。n-1,n.
每盞燈都對應一個開關,開關按一次可以將對應的燈的狀態改變一次(亮着的熄滅,熄滅的點亮)
有個人很無聊,真的很無聊。。。
他按如下規律按燈的開關:
1,2,3,4,。。。(1及其倍數)
2,4,6,8,。。。(2及其倍數)
3,6,9,12 。。。(3及其倍數)
4  8  。 。 。。。(4及其倍數)
5  。 。 。 。。。(5及其倍數)
。 。 。 。 。。。(省略了很多行)
。 。 。 。 。。。(n及其倍數,也就是隻有一個n)
過了很久很久,真的很久。。。他終於完成了,然後他要開始數有多少燈還亮着。

Input

每行一個n(1<=n<=109

Output

對於每個n輸出最後亮着的燈的數量

Sample Input

10100

Sample Output

790

找規律...

假設所有燈初始狀態爲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

A^B == B^A?

Time Limit: 2 Seconds      Memory Limit: 65536 KB

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

2
10

Sample Output

4.00000
-1

要注意到一句話:輸入的是ax中較小的那個,如果沒有這句話的話就又是另一種做法了我們可以對方程兩邊同時取對數,從而得到:ln(a)/a=ln(x)/x移一下項得到f(x)=ln(a)/a-ln(x)/x,

求導可以計算得到1-ln(x)f(x)在(0e)上單調遞減,在(e+無窮)上單調遞增,x=e的時候f(x)有最小值。

 

而且f(x)x軸的兩個交點就是所謂的可行解ab

那麼我們很顯然的可以得到ab分列於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

3124

Sample Output

123
1 1 2 3 5 8 ... 要使切的邊儘量小,並且任意三段能組成三角形

#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 MB
Submit: 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

30 01 12 230 01 12 3

Sample Output

a is the lucky boy.b is the lucky boy.

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代碼:

  1. #include<stdio.h>  
  2. int s[45];  
  3. char str[7][10]={"Saturday","Sunday","Monday","Tuesday","Wednesday","Thursday","Friday"};  
  4. int main()  
  5. {  
  6.     s[0]=0;  
  7.     for(int i=1;i<=44;i++)  
  8.     {  
  9.         int flag=i%7;  
  10.         int ans=1;  
  11.         for(int j=1;j<=i;j++)  
  12.             ans=(ans*flag)%7;  
  13.         s[i]=ans;  
  14.     }  
  15.     for(int i=1;i<=44;i++)  
  16.         {s[i]+=s[i-1];}  
  17.     int t;  
  18.     while(scanf("%d",&t)!=EOF)  
  19.     while(t--)  
  20.     {  
  21.         int n;  
  22.         scanf("%d",&n);  
  23.         int ans=(n/42%7*(s[42]%7)%7+s[n%42]%7)%7;  
  24.          printf("%s\n",str[ans]);  
  25.     }  
  26. }  

通過打表發現週期是294,那麼就簡單了

  1. #include <stdio.h>  
  2. #include <string.h>  
  3. #include <algorithm>  
  4. using namespace std;  
  5.   
  6. char day[10][10] = {"Saturday","Sunday""Monday""Tuesday""Wednesday""Thursday""Friday"};  
  7. int s[300];  
  8.   
  9. int work(int n)  
  10. {  
  11.     int sum = 1,i;  
  12.     for(i = 1;i<=n;i++)  
  13.     {  
  14.         sum = sum*n;  
  15.         sum%=7;  
  16.     }  
  17.     return sum;  
  18. }  
  19.   
  20. int main()  
  21. {  
  22.     int t,n,i,j,len;  
  23.     s[0] = 0;  
  24.     for(i = 1;i<=294;i++)  
  25.     {  
  26.         s[i] = s[i-1]+work(i);  
  27.         s[i]%=7;  
  28.     }  
  29.     scanf("%d",&t);  
  30.     while(t--)  
  31.     {  
  32.         scanf("%d",&n);  
  33.         n%=294;  
  34.         printf("%s\n",day[s[n]]);  
  35.     }  
  36.   
  37.   
  38.     return 0;  
  39. }  


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): 225
Problem 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
We have carefully selected several similar problems for you:  4919 4918 4917 4916 4914

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;
}





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章