1. 程式人生 > 實用技巧 >P4349 [CERC2015]Digit Division 思維題 數論

P4349 [CERC2015]Digit Division 思維題 數論

題意:

有一個\(N\)位的數字,將其分割,保證每個區間裡的數字可以被\(M\)整除,輸出方案數,答案對\(10^9+7\)取模

範圍&性質:\(1\le N\le 3\times10^5,1\le M\le 10^6\)

分析:

第一眼\(O(n^2)\)DP,一看資料範圍,放棄。思考怎麼優化,我們發現對於DP來說,每一個點都是由之前能夠斷開的地方轉移而來,那麼影響答案的只有可劃分的間隔,所以\(O(n)\)的掃一遍記錄能夠斷開的區間個數,且兩個斷點之間的區間一定能被\(M\)整除,最後只需要判斷一下最後一段區間能否被\(M\)整除,若可以,那麼答案就是$ 2^{斷點個數} $

程式碼:

#include<bits/stdc++.h>

using namespace std;

namespace zzc
{
	const int mod = 1e9+7;
	const int maxn = 3e5+5;
	char ch[maxn];
	int n,m,cnt=0,tmp=0;
	
	long long qpow(int x,int y)
	{
		long long res=1;
		while(y)
		{
			if(y&1) res=res*x%mod;
			x=(long long)x*x%mod;
			y>>=1;
		}
		return res;
	}
	
	void work()
	{
		scanf("%d%d",&n,&m);
		scanf("%s",ch+1);
		for(int i=1;i<n;i++)
		{
			tmp=(tmp*10+ch[i]-'0')%m;
			if(!tmp)
			{
				cnt++;
			}
		}
		tmp=(tmp*10+ch[n]-'0')%m;
		if(tmp)
		{
			printf("0\n");
			return ;
		}
		else printf("%lld",qpow(2,cnt));
	}
	
}

int main()
{
	zzc::work();
	return 0;
 }