8月1日解题报告

来源:互联网 发布:阿里云200m无限流量 编辑:程序博客网 时间:2024/05/16 00:35

hdu 1164

输入一个数,要求输出所有因子乘积的形式,并从小到大排列,数字与数字之间用“*”隔开,解决这类问题不需要素数打表,只需要用唯一分解定理即可。

#include<iostream>#include<cstdio>using namespace std;int main(){    int n,m,t;    while(cin>>m)    {        t=m;              //给m另外赋值,为了区别因数是一个还是有多个        for(int i=2;i<=m;i++)    //从2开始,一直到m数字本身        {            if(t%i==0)               //如果能被整除,就一直除,知道除尽这个数为止            {                while(t%i==0)                {                    if(t==m)              //如果是第一个因子,那么整除前应该跟m相等                      printf("%d",i);                    else                       printf("*%d",i);     //如果不是,则按一般情况处理                    t=t/i;         //一直整除,知道不能整除为止                }            }        }        cout<<endl;    }    return 0;}

hdu 1211

题目理解起来颇为费劲,不过看明白了就很简单了。
给你p、q、e要你求出d,然后根据后面给出的数字,作为小c代入M = D(c) = c(d) mod n,求出来的M的值用字符的形式输出即可。

#include<iostream>#include<cstdio>using namespace std;int main(){    long long p,q,e,l,a;    while(cin>>p>>q>>e>>l)    {    while(l--)    {        cin>>a;        long long n,fn,d,c,sum=1,i;        n=p*q;        fn=(p-1)*(q-1);        for(i=1;;i++)          if((i*e)%fn==1)          {             d=i;            //暴力求d             break;          }        for(int j=1;j<=d;j++)          sum=sum*a%n;             printf("%c",sum);      //求出M并且以字符的形式输出    }    cout<<endl;    }    return 0;} 

hdu 1215

跟1164类似,也是求因子数,只不过是要求的是因子数之和,在这里要注意一个问题,因为数据比较大,循环开的大小只需要根号m即可,因为每个数的因子都是成对出现的,必然有一个因子大于或等于根号m,而另一个因子小于或等于根号m。

#include<iostream>using namespace std;int main(){    int n,m;    cin>>n;    while(n--)    {        int sum=1;        cin>>m;        for(int i=2;i*i<=m;i++)     //避免超时,循环次数减少为根号            if(m%i==0)            {                if(i!=m/i) sum=sum+i+m/i;      //得到一个因子,并且借此把另一个因子也求出来加上去                else sum=sum+i;            }        cout<<sum<<endl;    }    return 0;} 

hdu 1222

点拨:本题的本质是求两个数是否有大于1的公因数

#include<iostream>using namespace std;int gcd(int x,int y){    int p;    while(x%y)    {        p=x%y;        x=y;        y=p;    }    return y;}int main(){    int n;    cin>>n;    while(n--)    {        int a,b,t;        cin>>a>>b;        if(a<b)        {            t=a;            a=b;            b=t;        }        if(gcd(a,b)==1)          cout<<"NO"<<endl;        else          cout<<"YES"<<endl;    }    return 0;}

hdu 1286

首先应该求出所有素因子,表示成唯一分解定理的形式,本题可以理解为求一个数n以内与n互素的数的个数。运用欧拉公式

  N(n)=n*(1-1/p1)*(1-1/p2)···(其中p1、p2为能被n整除的素因子)
#include<iostream>using namespace std;int main(){    int n,m,t;    cin>>n;    while(n--)    {        cin>>m;        int sum=m;        for(int i=2;i<=m;i++)        {            if(m%i==0)            {                sum=sum/i*(i-1);                while(m%i==0)                  m=m/i;            }        }        if(m>1) sum=sum/m*(m-1);        cout<<sum<<endl;    }    return 0;}

hdu 1299

通常给出的思路是:可以暴力求解,比如输入4, 就从5开始,一直寻找,直到所有结果都找到为止。于是就要考虑循环的跳出条件,因为开始你并不知道这个数的结果有多少种。运用数学知识,1 / x + 1 / y = 1 / n,假设x,y一大一小,即x>=y。则1/x<=1/y,所以有1/n<=1/y+1/y=2/y,变形得到较小的那个数y的范围是y<2n(注:x,y都必须大于n)。

因此用循环解答可以得到如下
for(int y=n+1;y<=2n;y++) //时间复杂度为n,即线性运算

范围条件都选好了,那么怎么判断该数是否满足条件呢?
将式子1 / x + 1 / y = 1 / n变形,得到1/x=1/n-1/y,再通分,将等式两边同时分子分母交换位置。
得到x=yk/(y-k) ,由x规定为整数可知,只要判断yk是否整除y-k即可得到结果是否满足条件。
另外,如果要考虑y是不是数据过大,可以进一步变形,令y=k+i,而x=k^2/i+k,
因此只要判断k的平方是否整除i即可。
得到的循环为for(int i=1;i<=k;i++)。

不过要注意,题目所给的n的范围最大是10的九次方,按照常理来说,应该是超时了,不信的话诸位可以试试,输出的结果不是WA,而是Time Limit Exceeded。因为题目所给的数据太大了。

在这里要另外转换思路求解了

既然线性运算超时,就必然要减少一些不必要数字的循环,因此思考方向就要转换到在n到2n之间,有那些数字是满足条件的,要想出一个筛选的条件。

继续看公式1 / x + 1 / y = 1 / n,前面一种思路已经打开了我们的思维,得到了公式x=k^2/i+k,用k的平方是否整除i来判断是否满足条件。我们知道,一个数k,如果整除i(i大于0,小于k),那么i一定就是k的因子了,不过在这里我们要的是k的平方的因子个数。

很容想到唯一分解定理:对于任一自然数n皆可唯一的表示为素数之积
N = p1^a1 * p2^a2 * p3^a3 * … * pn^an

#include<iostream>using namespace std;int main(){    long long s[100000],t;    long long i,j,k=0;    memset(s,0,sizeof(s));         for(i=2;i<100000;i++)         //素数打表    {        if(s[i]==0)        {            for(j=i*2;j<100000;j=j+i)              s[j]=1;        }    }    for(i=2;i<100000;i++)    {        if(s[i]==0)          s[k++]=i;    }    s[k]='\0';    cin>>t;    for(int count=1;count<=t;count++)    {        long long a,h,sum=1;        cin>>a;        for(i=0;s[i]!='\0';i++)            //找出素因子        {            h=0;            while(a%s[i]==0)                 //整除至尽            {                a=a/s[i];                h++;            }            sum=sum*(2*h+1);                  //根据公式求出个数        }        if(a>1) sum=sum*3;                //判断a为素数的情况        sum=sum/2+1;        cout<<"Scenario #"<<count<<":"<<endl;        cout<<sum<<endl<<endl;    }    return 0;}
0 0
原创粉丝点击