• 【CF1558B】Up the Strip


    题目

    题目链接:https://codeforces.com/problemset/problem/1558/B
    你有一个正整数 (n),当 (n>1) 时,可以选择以下两种操作:

    1. 选择一个在 ([1,n)) 范围内的整数 (x),让 (n) 减去 (x)
    2. 选择一个在 ([2,n]) 范围内的整数 (x),让 (n) 除以 (x) 并下取整。

    求有多少种方案使得 (n) 变为 (1)。答案对 (m) 取模。
    (nleq 4 imes 10^6)(m) 是质数。(simplified version:(nleq 2 imes 10^5))。
    时限 6s。

    思路

    (f[i]) 表示变到 (i) 的方案数。simplified version 的话由于 (lfloorfrac{i}{j} floor) 只有 (O(sqrt{i})) 种取值,直接整除分块就可以了。时间复杂度 (O(nsqrt n))
    而这道题的话就不考虑刷表,考虑如何转移到 (f[i])。如果一个数除以 (j) 后下去整等于 (i),那么这个数的范围显然是 ([ij,(i+1)j-1])。那么直接枚举 (j),记一下后缀和即可。
    时间复杂度 (O(sum_{i=1}^n lfloorfrac{n}{i} floor)=O(nlog n))

    代码

    /*
    #pragma GCC optimize("Ofast")
    #pragma GCC optimize("unroll-loops")
    #pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,avx2,tune=native")
    */
    #include <bits/stdc++.h>
    #define YES printf("YES
    ")
    #define Yes printf("Yes
    ")
    #define NO printf("NO
    ")
    #define No printf("No
    ")
    #define pb push_back
    #define mp make_pair
    #define fi first
    #define se second
    using namespace std;
    typedef long long ll;
    typedef long double ld;
    typedef unsigned long long ull;
    
    const int N=4000010;
    int Q,n,MOD,f[N],g[N];
    
    int main()
    {
    	//cerr<<(sizeof(f)+sizeof(g))/1024/1024<<"
    
    ";
    	scanf("%d%d",&n,&MOD);
    	f[n]=g[n]=1;
    	for (int i=n-1;i>=1;i--)
    	{
    		f[i]=g[i+1];
    		for (int j=2;i*j<=n;j++)
    		{
    			int l=i*j,r=min(n,(i+1)*j-1);
    			if (l>r) continue;
    			f[i]=((f[i]+g[l])%MOD-g[r+1])%MOD;
    		}
    		g[i]=(g[i+1]+f[i])%MOD;
    	}
    	cout<<(f[1]%MOD+MOD)%MOD;
    	return 0;
    }
    
  • 相关阅读:
    c#,简单的冒泡排序
    uwp,c#,listView与gridView列表控件进阶
    使用gensim之KeyedVectors操作词向量模型
    python时间戳
    通过Python查找目录下含有指定字符串的所有文件
    聚类之DBSCAN
    使用pyhanlp进行分词
    将Python对象和变量保存在本地
    通过selenium进行博客备份
    matplotlib颜色代码
  • 原文地址:https://www.cnblogs.com/stoorz/p/15186302.html
Copyright © 2020-2023  润新知