HDU4669_Mutiples on a circle
生活随笔
收集整理的這篇文章主要介紹了
HDU4669_Mutiples on a circle
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題目的意思是給你一些數字a[i](首位相連),現在要你選出一些連續的數字連續的每一位單獨地作為一個數位。現在問你有多少種選擇的方式使得選出的數字為k的一個倍數。
其實題目是很簡單的。由于k不大(200),總共的數字個數為50000,所以我們對于當前走到的每一個數字最多的狀態數目也只有50000*200個。
同時由于是循環的,我們可以使長度增倍,這樣就可以保證序列是循環的了。
不過注意,增倍后空間是開不下的,所以需要使用循環的滾動數組。
同時注意遞推的細節,還有有的a[i]不止一位數,不能直接取模。
?
#include <iostream> #include <cstdio> #include <cstring> #define maxn 50050 typedef long long ll; using namespace std;int a[2*maxn],f[2*maxn],n,m,k,tep,cur,w[2*maxn]; int s[maxn][205]; ll ans;void init_(int x) {for (int i=0; i<k; i++) s[x][i]=0; }int count(int x) {if (x<10) return 1;if (x<100) return 2;if (x<1000) return 3;return 4; }int get(int x) {if (x==1) return 10;if (x==2) return 100%k;if (x==3) return 1000%k;return 10000%k; }int power(int x,int y) {int tot=1;while (y){if (y&1) tot=(tot*x)%k;y>>=1;x=(x*x)%k;}return tot; }int main() {while (scanf("%d%d",&n,&k)!=EOF){ans=0;w[0]=0,f[0]=0;for (int i=1; i<=n; i++){scanf("%d",&a[i]);a[i+n]=a[i];w[i]=count(a[i]);w[i+n]=count(a[i+n]);}for (int i=1; i<=2*n; i++) f[i]=(f[i-1]*get(w[i])+a[i])%k;for (int i=1; i<=2*n; i++) w[i]+=w[i-1];for (int i=1; i<=n; i++){init_(i);s[i][a[i]%k]++;for (int j=0; j<k; j++) s[i][(get(w[i]-w[i-1])*j+a[i])%k]+=s[i-1][j]; }for (int i=n+1; i<=2*n; i++){int qq=i-n-1;if (qq==0) qq=n;init_(i-n);s[i-n][a[i]%k]++;for (int j=0; j<k; j++) s[i-n][(get(w[i]-w[i-1])*j+a[i])%k]+=s[qq][j];cur=(f[i-n-1]*power(10,w[i]-w[i-n-1]))%k;cur=((f[i]-cur)%k+k)%k; s[i-n][cur]--; ans+=s[i-n][0]; }printf("%I64d\n",ans);}return 0; }?
轉載于:https://www.cnblogs.com/lochan/p/3446851.html
總結
以上是生活随笔為你收集整理的HDU4669_Mutiples on a circle的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 沃特股份是做什么的
- 下一篇: Daily Scrum02 12.04