2022 8.22 T1 函数变化(change.cpp)
T1 函数变化(change.cpp)
题目描述
【问题描述】
我们在幼儿园的时候学习过函数的概念,函数是给定一组自变量的值
得到一组因变量的值。比如 d(p)就是一个最基础的函数形式,我们也可以
叫做把 d 在 p 上作用了一次,如果作用两次就是 d(d(p))。
现在给定函数 (M|x:表示 M 整除 x)
同时给定 M,问有多少个数 x 第一次等于 1 需要作用 N 次该函数
【输入格式】
第一行两个整数 M,N。
【输出格式】
一行一个整数代表答案对 10^9+9 取模后的值
【样例输入】
5 3
【样例输出】
4
【样例解释】
四个答案分别是 3、20、24、125。
【数据范围】
对于 30%的数据,N,M<=100;
对于 50%的数据, 1<N<=5e4,1=<M<=5e4
对于额外 20%的数据,N<=1e6,M=2;
对于 100%的数据,1<N<=1e6,1=<M<=1e6;
是不是非 常 简 单? 建议暂停思考10分钟。
官方题解
我们可以考虑分情况讨论。
当 M>N 的时候,每次+1,最多加 N 次,那么这个数还是不会被 M 整除 所以不会存在重复的情况,所以答案是
如果 M=N 的时候,第一次为 M,执行 M-1 次-1 操作后,答案为 1,那么就不是作用 N 次第一次等于 1,所以答案舍弃,所以为
接下来考虑 M<N 的时候,我们可以用总的答案 ——不合理的答案(执行-1 操作后答 案刚好是 M 的倍数的数字) 如果这一次操作执行之后答案为 M 的倍数,那么数量和 M 次操作前答案为 M 的倍数 的数一样多。这样的数有多少个呢?中是 M 的倍数的数的个数,具体有多少个呢,既 然这个数是 M 的倍数,那么就是有 X*M 变换而来的,所以有 个 所以当 M<N 的时候,答案为
我的思路
枚举法
1.至多枚举至这个数
2.可以通过保存之前的回跳次数来进行判断
显然,虽然是对的,但是空间与时间都太高了
10pts
#include<bits/stdc++.h> using namespace std; const int N=1e8+5; //subtask 10% //尝试枚举每一个数,利用之前留下的数,进行O(1)判断 const int M=1e9+9; int save[N],n,m,ans=0; int main(){ freopen("change.in","r",stdin); freopen("change.out","w",stdout); cin>>m>>n; save[1]=0; for(long long i=2;i<=pow(m,n);i++){ long long cnt=((i/m)+(i%m!=0))*m-i; cnt+=save[(i/m)+(i%m!=0)]+1; if(cnt==n) ans++,ans%=M; save[i]=cnt; } cout<<ans%M; }Std
#include<cstdio> #include<cstring> #include<algorithm> #define ll long long using namespace std; const ll maxn=1010101; const ll p=1000000000+9; ll a[maxn],n,m; int main() { freopen("change.in","r",stdin); freopen("change.out","w",stdout); scanf("%lld%lld",&m,&n); a[1]=1; for(ll i=2;i<m;i++) a[i]=a[i-1]*2%p; a[m]=(a[m-1]*2-1)%p; a[m+1]=a[m]*2%p; for(ll i=m+2;i<=n;i++) a[i]=(a[i-1]*2-a[i-m-1])%p; printf("%lld\n",(a[n]+p)%p); return 0; }
本文来自博客园,作者:haozexu,转载请注明原文链接:https://www.cnblogs.com/haozexu/p/18281796

浙公网安备 33010602011771号