D 牛牛的呱数 思维题+bfs
链接:https://ac.nowcoder.com/acm/contest/5205/D
题意:给出一堆数字串,给出一个模数p
让我们找出一个这堆数字串的组合方式,满足模p之后等于0
每一个数字串都有无限个,可以用多个,也可以不用;
思路:我们要进行拼接,就要将前面的数字*后面的数字的位数再+上后面的数字,才能算是拼接成功
于是,我们得先初始化出倍数mod p 之后的数组
然后,对于每一个数字串,我们处理出其modp之后剩下的数以及其长度
将每一个串作为第一个串的情况都记录下来,放进优先队列中
然后操作都对队列中所有的数字进行依次拼接
拼接之后,如果原先已经有该模数的长度比较小的,就不需要入队
反正更新权值并且入队
直到操作完毕。。。
但是:我并不知道bfs这个过程的复杂度。。。
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=1000005; 4 const int inf=0x3f3f3f3f; 5 char s[maxn];//存当前大数 6 int dp[204]; 7 int ten[maxn];//记录10的倍数的mod 8 int rmd[104];//记录n个大数的mod 9 int len[103];//记录n个大数的长度 10 struct node{ 11 int mod,len;//队列状态。 12 }; 13 //优先队列比较函数 14 struct cmp{ 15 bool operator()(node a,node b){ 16 //注意,优先队列本来是从大到小,所以这里反着写 17 //即:这里为从小到大排序 18 return a.len>b.len; 19 } 20 }; 21 int main(){ 22 int n,p; 23 scanf("%d%d",&n,&p); 24 //处理10的倍数的mod 25 ten[0]=1; 26 for(int i=1;i<maxn;i++) ten[i]=(ten[i-1]*10)%p; 27 //处理大数的mod和长度 28 for(int i=1;i<=n;i++){ 29 scanf("%s",s+1); 30 len[i]=strlen(s+1); 31 for(int j=1;j<=len[i];j++){ 32 rmd[i]=(rmd[i]*10+(s[j]-'0'))%p; 33 } 34 } 35 //全部更新为inf 36 memset(dp,inf,sizeof(dp)); 37 priority_queue<node,vector<node>,cmp> pq; 38 //初始化已有数值的dp 39 for(int i=1;i<=n;i++) 40 dp[rmd[i]]=min(dp[rmd[i]],len[i]); 41 //把n个初始状态推进去 42 for(int i=0;i<p;i++) 43 if(dp[i]!=inf) 44 pq.push(node{i,dp[i]}); 45 while(!pq.empty()){ 46 node cur=pq.top(); 47 pq.pop(); 48 if(cur.mod==0){ 49 printf("%d\n",cur.len); 50 return 0; 51 } 52 //每种大数都遍历一遍,因为每种都有无限个 53 for(int i=1;i<=n;i++){ 54 node nex; 55 //把新大数加在最右边。 56 nex.mod=(cur.mod*ten[len[i]]%p+rmd[i])%p; 57 nex.len=cur.len+len[i]; 58 if(dp[nex.mod]>nex.len){ 59 dp[nex.mod]=nex.len; 60 pq.push(nex); 61 } 62 } 63 } 64 printf("-1\n"); 65 }