zoukankan      html  css  js  c++  java
  • MZOJ #71 maple做数学题

     分析

    一道不可多得的好题啊

    MZOJ数据过水,可以骗80分

    好吧我们说正解

    首先,k一定是个素数

    其次,如果k > 320000(或k * k >= n时,注意 k * k 可能会爆longlong),那么满足条件的数最多只有一个

    接下来,我们进入正题,

    如题,说明满足条件的数只能含有k及k以上的素数因子

    直接线筛可以骗分,但是看看r的范围

    不好意思打扰了

    还有一个条件:必须含有k

    好的,我们该怎么办

    数据范围这么大,不可能直接算

    不如放宽限制,看这个答案可不可以从其他答案得到

    没错,我想到了搜索,把一个大问题变成小问题来解

    嗯,接下来,状态

    需要一个上限,其实下限不是那么重要,剪掉就好

    需要一个状态存素数

    需要的部分显然太大,不好考虑

    我们考虑不要的部分,也就是小于k的素数的倍数

    至于素数,线筛就好 

    最终答案很好想

    怎么实现呢,其实交给相同子问题就好,比如,筛掉含prime[m]的数:

    嗯,这题可以记忆化

    还有一些小细节,看核心:

    代码

      1 /**************************
      2 User:Mandy.H.Y
      3 Language:c++
      4 Problem:math
      5 Apgorithm:
      6 **************************/
      7 
      8 #include<bits/stdc++.h>
      9 #define Max(x,y) ((x) > (y) ? (x) : (y))
     10 #define Min(x,y) ((x) < (y) ? (x) : (y))
     11 
     12 using namespace std;
     13 
     14 typedef long long ll;
     15 
     16 const long long maxn = 320000+5;
     17 const long long mod = 1e9 + 7;
     18 const long long ni = 5e8 + 4;
     19 const int N = 10010;
     20 const int M = 110;
     21 
     22 ll l,r,k,cnt=0,ans;
     23 ll dp[N][M];
     24 ll prime[maxn];
     25 bool vis[maxn];
     26 
     27 template<class T>inline void read(T &x){
     28     x = 0;bool flag = 0;char ch = getchar();
     29     while(!isdigit(ch)) flag |= ch == '-',ch = getchar();
     30     while(isdigit(ch)) x = (x << 1) + (x << 3) + (ch ^ 48),ch = getchar();
     31     if(flag) x = -x;
     32 }
     33 
     34 template<class T>void putch(const T x){
     35     if(x > 9) putch(x / 10);
     36     putchar(x % 10 | 48);
     37 }
     38 
     39 template<class T>void put(const T x){
     40     if(x < 0) putchar('-'),putch(-x);
     41     else putch(x);
     42 }
     43 
     44 void file(){
     45     freopen("math.in","r",stdin);
     46     freopen("math.out","w",stdout);
     47 }
     48 
     49 void readdata(){
     50     read(l);read(r);read(k);
     51 }
     52 
     53 void get_prime(){//线性筛 
     54 
     55     vis[0] = 1;
     56     vis[1] = 0;
     57     
     58     for(ll i = 2;i <= k; ++ i){
     59         if(!vis[i]) prime[++cnt] = i;
     60         for(ll j = 1;j <= cnt && prime[j] * i <= k; ++ j){
     61             vis[prime[j] * i] = 1;
     62             if(i % prime[j] == 0) break;
     63         }
     64     }
     65     
     66 }
     67 
     68 ll DFS(ll n,ll m){
     69     //表示1~n减去前m个质数及其倍数后,剩余数的和
     70     //也就是1~n中最小的质因子都比prime[m]大的数的和 
     71     ll ans = 0;
     72     if(n < 2) return n;
     73     //没有比二小的质数 
     74     if(n < N && m < M && dp[n][m]) return dp[n][m];
     75     //记忆化 
     76     if(!m) ans = (1+n) % mod * (n%mod) % mod * ni % mod;
     77     //1~n中所有数的和 
     78     else {
     79         if(prime[m] > n) {
     80             
     81             while(m && prime[m] > n) --m;
     82             //保证prime[m]<n,反正大于n的时候又不能筛 
     83             ans = DFS(n,m); 
     84             
     85         } else ans = (DFS(n,m-1) - 
     86                       DFS(n/prime[m],m-1) % mod * prime[m] % mod + mod) % mod;
     87     }
     88     
     89     if(n < N && m < M) dp[n][m] = ans;
     90     return ans;
     91 }
     92 
     93 void work(){
     94     
     95     get_prime();
     96     
     97     ans = (DFS(r/prime[cnt],cnt-1) % mod *prime[cnt] % mod - 
     98           (DFS((l-1)/prime[cnt],cnt-1)*prime[cnt] % mod) + mod ) % mod;
     99     //看这里,保证了求出了r/k以内所有只含有k及比k大的因子的数的和
    100     //且乘以k不会超r,保证了一定含有k,且k为最小 
    101     put(ans);
    102 }
    103 
    104 bool Isprime(){
    105     for(ll i = 2;i * i <= k; ++ i)
    106         if(k % i == 0) return 0;
    107     return 1;
    108 }
    109 
    110 int main(){
    111 //    file();
    112     readdata();
    113     
    114     if((!Isprime()) || k > r){
    115         puts("0");
    116         return 0;
    117     }
    118     
    119     if(k >= 320000 || (k * k >= r)){
    120         if(k >= l ) put(k % mod);
    121         else puts("0"); 
    122     } else work();
    123     return 0; 
    124 }
    View Code
    非做顽石不可,哪管他敬仰暗唾
  • 相关阅读:
    2018 徐州网络赛A
    2018 徐州网络赛 G
    Split The Tree(dfs序+树状数组)
    A Question of Ingestion(Dp)
    Starting a Scenic Railroad Service(前缀和+差分)
    Rendezvous on a Tetrahedron (模拟)
    7032: Knightsbridge Rises(网络流+dfs)
    7033: Lounge Lizards(lis)
    并发服务器
    fork和exec函数
  • 原文地址:https://www.cnblogs.com/Mandy-H-Y/p/11444587.html
Copyright © 2011-2022 走看看