zoukankan      html  css  js  c++  java
  • 樱花(信息学奥赛一本通 1624)

    【题目描述】

    原题来自:HackerRank Equations

    求不定方程: 1/x + 1/y = 1/n!

    的正整数解 (x,y)的数目。

    【输入】

    一个整数 n

    【输出】

    一个整数,表示有多少对 (x,y) 满足题意。答案对 109+7 取模。

    【输入样例】

    2

    【输出样例】

    3

    【提示】

    样例说明

    共有三个数对 (x,y) 满足条件,分别是 (3,6),(4,4) 和 (6,3)。

    数据范围与提示:

    对于 30% 的数据,n≤100;

    对于全部数据,1n106 。


     

    (这里不得不吐糟一下,书上把题目打错了啦,n!写成了n,害得我还以为这道题可以暴力去做,结果光荣的爆零了(▼⊿▼))

    首先呢就是用数学方法把这个不定方程变化一下,令y=n+a(x、y肯定比n大啦,可以自己推导一下),很容易就得到了 x = (n!*n!) / a+ n!

    那么因为n!为整数、x也为整数,所以(n!*n!) / a一定也为整数。那要求x的个数的话就是要求满足(n!*n!) / a为整数的a的个数

    所以说这道题很快就转化成了一道求约数个数的题目。

    然后就是唯一分解定理约数个数定理...

    上代码:

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int N=1e6+1,M=1e9+7;
     4 int a[N],n,v[N],cnt,b[N],num[N];//b[x]表示x的最小质因子是质数中的第几号 
     5 long long ans=1;
     6 int read()
     7 {
     8     int x=0,f=1;
     9     char ch=getchar();
    10     while(ch<'0'||ch>'9')
    11     {
    12         if(ch=='-') f=-1;
    13         ch=getchar();
    14     }
    15     while(ch>='0'&&ch<='9')
    16     {
    17         x=x*10+ch-'0';
    18         ch=getchar();
    19     }
    20     return x*f;
    21 }
    22 void write(int x)
    23 {
    24     if(x<0)
    25     {
    26         putchar('-');
    27         x=-x;
    28     }
    29     if(x>9) write(x/10);
    30     putchar(x%10+'0');
    31 }
    32 void pre()
    33 {
    34     for(int i=2;i<=1000000;i++)
    35     {
    36         if(!v[i])a[++cnt]=i,b[i]=cnt;
    37         for(int j=1;j<=cnt&&a[j]*i<=1000000;j++)
    38         {
    39             v[i*a[j]]=1;b[i*a[j]]=j; 
    40             if(i%a[j]==0)break;
    41         }
    42     }
    43 }
    44 void ff(int x)
    45 {
    46     while(x!=1)
    47     {
    48         num[b[x]]++;//num[i]表示i这个序号代表的质因子出现的次数(也就是b[i]的幂的次数啦) 
    49         x/=a[b[x]];//x不断更新 
    50     }
    51 }
    52 int main()
    53 {
    54     
    55     n=read();
    56     pre();
    57     for(int i=2;i<=n;i++)
    58         ff(i);
    59     for(int i=1;i<=cnt;i++)
    60         ans=ans*(num[i]*2+1)%M;
    61     printf("%lld",ans);
    62     return 0;
    63 }

    //参考:这位大佬讲的hin好,点击%大佬的博客

  • 相关阅读:
    [MetaHook] Find a function signature
    [MetaHook] GameUI hook
    [MetaHook] BaseUI hook
    一些常用软件的网络端口协议分类介绍
    Visual C++中最常用的类与API函数
    Ubuntu常用软件安装
    C++字符串完全指引
    C++资源之不完全导引
    超过 130 个你需要了解的 vim 命令
    Little-endian和Big-endian
  • 原文地址:https://www.cnblogs.com/ljy-endl/p/11378174.html
Copyright © 2011-2022 走看看