標籤:style class blog code http tar
今天居然沒參考任何資料解決了這道數位DP,事先只是搞一道數論題練練;
思路:求SUM[1]-SUM[N]的二進位的乘積mod1000000007;
N<=10^15;BZOJ的題不會是幾個簡單的FOR就完結的,
假如N的二進位是:1001001;
位元:1234567
那麼當第一位是0的情況:那麼數就是000000-111111
序號: 123456-123456
發現我們可以用排列組合算出二進位有1-6個1的數比如:1個1就是C[6][1],2個1就是C[6][2],......
當第一位是0:那麼就看下一位為1的位置,去枚舉計算,注意第一位為1後面全部為0的情況我們要考慮。
說的比較不靠譜。
比如:第一位為0;那麼枚舉1-6位的位置;
當第一位為1是:可能1-6位都為0,所以前面的這個1要考慮,
可以自己畫畫
#include<stdio.h>#include<iostream>#include<string.h>#include<math.h>using namespace std;#define N 10000007typedef long long ll;ll c[61][61];int b[61];ll kuai(ll a,ll b)//快速米{ ll ans=1; while (b) { if (b&1) ans=ans*a%N; a=a*a%N; b/=2; } return ans;}int main(){ ll n; int t=0; for (int i=0;i<=61;i++)//預先計算排列組合 c[i][0]=1; for (int i=1;i<=60;i++) for (int j=1;j<=60;j++) c[i][j]=(c[i-1][j]+c[i-1][j-1]); scanf("%lld",&n); while (n) { t++; if (n&1) b[t]=1; n/=2; } int k=0; ll ans=1; for (int i=t;i>=1;i--) if (b[i]) { ans=ans*(k+1)%N; for (int j=1;j<=i-1;j++) ans=ans*kuai(j+k,c[i-1][j])%N; k++; } printf("%d\n",ans); return 0;}View Code