题解:P9006 [入门赛 #9] 神树大人挥动魔杖 (Hard Version)

1. 纯暴力(只过样例,0pts):

#include<bits/stdc++.h>
#define fast_gets ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std;
int ans[1005];
int main(){
   fast_gets
	int n,k;
	cin>>n>>k;
	for(int i=1;i<=9*pow(10,n-1);i++){
		for(int j=0;j<k;j++){
			if(i%k==j) ans[j]++;
		}
	}
	for(int i=0;i<k;i++) cout<<ans[i]<<' ';
   return 0;
}

代码就不解释了。

2. 差分(100pts):

思路:

精灵的个数为 \(9\times 10^{n-1}\) 可写为 \(10^n-10^{n-1}\)

同理可设有一个函数 \(f(n, k, i)\),表示从 \(1\)\(10^n - 1\) 之间所有数中模 \(k\) 余数为 \(i\) 的数的个数。那么,题目中的表达可以用以下的形式表示:

\(f(n, k, i) - f(n-1, k, i)\)

其中:

  • \(f(n, k, i)\) 表示前 \(10^n - 1\) 个数中,模 \(k\) 余数为 \(i\) 的个数。
  • \(f(n-1, k, i)\) 表示前 \(10^{n-1} - 1\) 个数中,模 \(k\) 余数为 \(i\) 的个数。

这个表达式表示的是在从 \(1\)\(10^n - 1\) 之间的数中,模 \(k\) 余数为 \(i\) 的数的个数与从 \(1\)\(10^{n-1} - 1\) 之间的数中,模 \(k\) 余数为 \(i\) 的数的个数之差。

每一组精灵至少有 \(\left \lfloor \frac{9\times 10^{n-1}}{k} \right \rfloor\) 个精灵,剩余 \(a \bmod k\) 个分别分到了 \(1\)\(a \bmod k\) 组中。

AC 代码(纯净版):

#include<bits/stdc++.h>
#define endl '\n'
#define ll long long
#define fast_gets ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std;
const int N=1e6+5,MOD=1e8+7;
int cnt[N];
ll f(ll a,ll b,ll c){
	ll ans=1;
	while(b){
		if(b&1) ans=ans*a%c;
		a=a*a%c;
		b>>=1;
	}
	return ans;
}
int main(){
    fast_gets
	int n,k;
	cin>>n>>k;
	ll maxn=(f(10,n-1,k)-1+k)%k;
	ll p=(f(10,n-1,MOD)-1-maxn+MOD)*f(k,MOD-2,MOD)%MOD;
	for(int i=0;i<k;i++){
		cnt[i]=-p;
		if(i>0&&i<=maxn) cnt[i]--;
	} 
	maxn=(f(10,n,k)-1+k)%k;
	p=(f(10,n,MOD)-1-maxn+MOD)*f(k,MOD-2,MOD)%MOD;
	for(int i=0;i<k;i++){
		cnt[i]+=p;
		if(i>0&&i<=maxn) cnt[i]++;
		cnt[i]=(cnt[i]+MOD)%MOD;
		cout<<cnt[i]<<' ';
	}
    return 0;
}
posted @ 2025-02-20 18:57  Kaori_Li  阅读(21)  评论(0)    收藏  举报
*/