LightOJ1028 1090 1138 Trailing Zeroes (I)(Ⅱ)(Ⅲ)[算数基本定理/打表/打表+二分]

C -   Trailing Zeroes (I)
Time Limit:2000MS     Memory Limit:32768KB     64bit IO Format:%lld & %llu

Description

We know what a base of a number is and what the properties are. For example, we use decimal number system, where the base is 10 and we use the symbols - {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}. But in different bases we use different symbols. For example in binary number system we use only 0 and 1. Now in this problem, you are given an integer. You can convert it to any base you want to. But the condition is that if you convert it to any base then the number in that base should have at least one trailing zero that means a zero at the end.

For example, in decimal number system 2 doesn't have any trailing zero. But if we convert it to binary then 2 becomes (10)2 and it contains a trailing zero. Now you are given this task. You have to find the number of bases where the given number contains at least one trailing zero. You can use any base from two to infinite.

Input

Input starts with an integer T (≤ 10000), denoting the number of test cases.

Each case contains an integer N (1 ≤ N ≤ 1012).

Output

For each case, print the case number and the number of possible bases where  N  contains at least one trailing zero.

Sample Input

      
      

3

9

5

2

Sample Output

      
      

Case 1: 2

Case 2: 1

Case 3: 1

Hint

   
   
For  9 , the possible bases are:  3  and  9 . Since in base  3 9  is represented as  100 , and in base  9 9  is represented as  10 . In both bases,  9  contains a trailing zero.

题意:
T组数据,每组有一个N,求出N在多少个进位下末尾为0

题解:
就是求出N的因数,但是不包括1

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<string>
#include<algorithm>
#include<queue>
#include<stack>
#include<set>
#include<map>
#include<vector>
#define edge segtree[id]
#define lson segtree[id<<1]
#define rson segtree[id<<1|1]
using namespace std;
typedef long long ll;
const int N=1e6+5;
bool mark[N];
int prim[N];
int cnt;
//题目N取值 1<=N<=1e12
//T <=1e4
void initial()
{
    cnt=0;
    for (int i=2 ; i<N ; ++i)
    {
        if (!mark[i])
            prim[cnt++]=i;

        for (int j=0 ; j<cnt && i*prim[j]<N ; ++j)
        {
            mark[i*prim[j]]=1;
            if (!(i%prim[j]))
                break;
        }
    }
}
ll divi(ll n)
{
    ll ans=1;
    for (int i=0 ; i<cnt && prim[i]*prim[i]<=n ; ++i)
    {
        if (!(n%prim[i]))
        {
            int s=0;
            while (!(n%prim[i]))
            {
                n/=prim[i];
                s++;
            }
            ans*=(s+1);
        }
    }
    return n>1?ans*(1+1):ans;//n>1代表n为素数 也是一个正因子 所以要加上
}
int main()
{
    initial();
    int T;
    scanf("%d",&T);
    for (int test=1 ; test<=T ; test++)
    {
        ll n;
        scanf("%lld",&n);
        printf("Case %d: %lld\n",test,divi(n)-1);//多了一个1因子 删去
    }
    return 0;
}



H -  Trailing Zeroes (Ⅱ)
Time Limit:2000MS     Memory Limit:32768KB     64bit IO Format:%lld & %llu

Description

Find the number of trailing zeroes for the following function:

nCr * pq

where n, r, p, q are given. For example, if n = 10, r = 4, p = 1, q = 1, then the number is 210 so, number of trailing zeroes is 1.

Input

Input starts with an integer T (≤ 10000), denoting the number of test cases.

Each case contains four integers: n, r, p, q (1 ≤ n, r, p, q ≤ 106, r ≤ n).

Output

For each test case, print the case number and the number of trailing zeroes.

Sample Input

      
      

2

10 4 1 1

100 5 40 5

Sample Output

      
      

Case 1: 1

Case 2: 6



题意:
T组数据,给n,r,p,q 求出C(n,r)*(p^q)结果的末尾有多少个0

题解:
能弄出0的 只有2*5 那我只需要统计这个组合数有多少个2和多少个5,再加上(p^q)的2或者5的个数,取小的一边
打表统计 1到1e6的数里面有多少个2多少个5就可以了

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<string>
#include<algorithm>
#include<queue>
#include<stack>
#include<set>
#include<map>
#include<vector>
#define edge segtree[id]
#define lson segtree[id<<1]
#define rson segtree[id<<1|1]
using namespace std;
typedef long long ll;
const int N=1e6+5;
ll five[N],two[N];
void initial()
{
    memset(five,0,sizeof(five));
    memset(two,0,sizeof(two));
    ll s1=0,s2=0;
    for (int i=2 ; i<N ; ++i)
    {
        int num=i;
        while (!(num%2))
        {
            s1++;
            num/=2;
        }
        num=i;
        while (!(num%5))
        {
            s2++;
            num/=5;
        }
        two[i]=s1;
        five[i]=s2;
    }
}
int main()
{
    initial();
    int T;
    scanf("%d",&T);
    for (int test=1 ; test<=T ; ++test)
    {
        int n,r,p;
        ll q;
        scanf("%d%d%d%lld",&n,&r,&p,&q);
        ll ans = min (two[n]-two[n-r]-two[r]+(two[p]-two[p-1])*q,five[n]-five[n-r]-five[r]+(five[p]-five[p-1])*q);
        printf("Case %d: %lld\n",test,ans);
    }
    return 0;
}




K -  Trailing Zeroes (III)
Time Limit:2000MS     Memory Limit:32768KB     64bit IO Format:%lld & %llu

Description

You task is to find minimal natural number  N , so that  N!  contains exactly  Q  zeroes on the trail in decimal notation. As you know  N! = 1*2*...*N . For example, 5! = 120, 120 contains one zero on the trail.

Input

Input starts with an integer T (≤ 10000), denoting the number of test cases.

Each case contains an integer Q (1 ≤ Q ≤ 108) in a line.

Output

For each case, print the case number and  N . If no solution is found then print  'impossible' .

Sample Input

     
     

3

1

2

5

Sample Output

     
     

Case 1: 5

Case 2: 10

Case 3: impossible



题意:
T组数据,每组有一个N,表示这个数的末尾有N个0,计算这是第几个阶乘才会有N个0

题解:
跟上面一个题一样,只有2*5才会构成0在末尾,阶乘中,2的个数肯定是比5大的,那我就不需要管2的个数,直接统计5的个数,打表统计1个5开始直到算到有超过1e8个5,统计过程过,因为数组不能存那么多,每隔100取记录一次,然后二分查询时,注意还原原来的数是乘以500,如果直接已经存在这个就直接输出,区别开0-100 还有超过100的记法,如果刚刚好等于那么多个0,输出这个数,如果不存在就输出'impossible' (我的这个解法大概是速度最慢了,因为要先打表,网上貌似有其他解法,我没有细看)

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<string>
#include<algorithm>
#include<queue>
#include<stack>
#include<set>
#include<map>
#include<vector>
#define edge segtree[id]
#define lson segtree[id<<1]
#define rson segtree[id<<1|1]
using namespace std;
typedef long long ll;
const int N=1e8;//最多1e8个0
const int M=1e6;
int sum[M];
int cnt;
void initial()//因为2的个数肯定系够的,甘姐系记录5的个数就得了
{
    sum[0]=1;
    int res=0;
    cnt=0;
    for (int i=1 ; ; ++i)
    {
        if (!(i%5))//看这个数有多少5
        {
            int s=0,m=i;
            while (!(m%5))
            {
                s++;
                m/=5;
            }
            res+=(s+1);
        }
        else
            res+=1;
        if (!(i%100))
        {
            sum[i/100]=res;
            cnt++;
        }
        if (res>N)
            break;
    }
}
int main()
{
    initial();
    int T;
    scanf("%d",&T);
    for (int test=1 ; test<=T ; ++test)
    {
        int n;
        scanf("%d",&n);
        printf("Case %d: ",test);
        if (n==1)
        {
            printf("5\n");
            continue;
        }
        int ans=lower_bound(sum,sum+cnt,n)-sum-1;
        ll res=sum[ans];
        if (res==n)
        {
            printf("%lld\n",ans*500);
            continue;
        }
        ll last;
        if (!ans)
        {
            for (int i=2 ; ; ++i)
            {
                if (!(i%5))
                {
                    int s=0,m=i;
                    while(!(m%5))
                    {
                        s++;
                        m/=5;
                    }
                    res+=(s+1);
                }
                else
                    res++;
                if (res>=n)
                {
                    if (res==n)
                        last=i;
                    else
                        last=-1;
                    break;
                }
            }
        }
        else
        {
            last=ans*100;
            for (int i=last+1 ; ; ++i)
            {
                if (!(i%5))
                {
                    int s=0,m=i;
                    while (!(m%5))
                    {
                        s++;
                        m/=5;
                    }
                    res+=(s+1);
                }
                else
                    res++;
                if (res>=n)
                {
                    if (res==n)
                        last=i;
                    else
                        last=-1;
                    break;
                }
            }
        }
        if (last==-1)
            printf("impossible\n");
        else
            printf("%lld\n",last*5);
    }
    return 0;
}


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Sigma函是指一个字的所有因子之和。给定一个字n,需要求出有多少个字的Sigma函是偶。\[2\] 为了解决这个问题,可以先筛选出n范围内的素(范围在10^6即可),然后对n进行素因子分解。对于每个因子,如果它的Sigma函中连乘的每一项都是偶,那么整个Sigma函就是偶。具体实现中,可以判断每个因子的平方根是否为偶,如果是偶,则减去(平方根+1)/2。\[1\] 另外,还可以使用O(1)的做法来解决这个问题。根据观察,所有的完全平方及其两倍的值都会导致Sigma函为偶。因此,可以直接计算n的平方根,然后减去(平方根+1)/2即可得到结果。\[3\] #### 引用[.reference_title] - *1* [Sigma Function](https://blog.csdn.net/PNAN222/article/details/50938232)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [【LightOJ1336】Sigma Function(论)](https://blog.csdn.net/qq_30974369/article/details/79009498)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值