日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

HDU 6304 Chiaki Sequence Revisited

發布時間:2025/4/16 编程问答 50 豆豆
生活随笔 收集整理的這篇文章主要介紹了 HDU 6304 Chiaki Sequence Revisited 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題目鏈接 : http://acm.hdu.edu.cn/showproblem.php?pid=6304 多校contest1 Problem Description

Chiaki is interested in an infinite sequence a1,a2,a3,..., which is defined as follows:

an={1an?an?1+an?1?an?2n=1,2n3


Chiaki would like to know the sum of the first n terms of the sequence, i.e. i=1nai. As this number may be very large, Chiaki is only interested in its remainder modulo (109+7).

Input

?

There are multiple test cases. The first line of input contains an integer T (1T105), indicating the number of test cases. For each test case:
The first line contains an integer n (1n1018). Output

For each test case, output an integer denoting the answer.

?

題目大意是求一個 奇怪序列的 前 n 項 和,n最壞情況達 1e18。 開始打了個表,發現在序列是從1開始的連續整數(每個整數出現的次數不同),除了數字 1是出現兩次,其他數字 如x 都是出現 lowbit(x)后綴0的個數+1 次。 如2(10) 出現2次 ,3(11) 出現1次,4(100) 出現3次,5(101)出現1次,6(110) 出現2次... 可以發現這是一個十分有特點的(類似2進制,有部分對稱性)的序列 接下來我們可以發現如果把1當做出現1次,出現在 2^n 上,如果占滿 ,次數總和剛好是 2^(n+1) -1 次,那么多出來的數似乎又沒有規律了,這時我們可以利用局部對稱與這個和二進制相似的特點,找到 第 n 個數 是數字多少(落在圖中的位置), 有兩種方法: 第一種 可以知道N(自減一后)對應的準確數字,但不知N落在的數字差幾次被填滿,不便計算。 1 void init(){ 2 P[0]=1;P[1]=2; 3 nP[0]=0;nP[1]=1; 4 for(int i=2;i<=62;++i){ 5 P[i]=2*P[i-1]; 6 nP[i]=P[i]-1; 7 } 8 } 9 10 ll getbound(ll N){ 11 ll bound=0; 12 for(int i=62;i>=1;--i){ 13 while(N>=nP[i]){ 14 N-=nP[i]; 15 bound+=P[i-1]; 16 } 17 } 18 return bound; 19 }

第二種 完全參照二進制,可知N(自減一后)所落在的數字最近的次數填滿數字,后來計算時很方便。

1 void init(){ 2 P[0]=1;P[1]=2; 3 nP[0]=0;nP[1]=1; 4 for(int i=2;i<=62;++i){ 5 P[i]=2*P[i-1]; 6 nP[i]=P[i]-1; 7 } 8 } 9 10 ll getbound(ll& N){ 11 ll bound=0; 12 for(int i=62;i>=1;--i){ 13 if(N>=nP[i]){ 14 N-=nP[i]; 15 bound+=P[i-1]; 16 } 17 } 18 return bound; 19 }

計算時可以可利用每個數字出現的次數,是1(2^0)的倍數的出現過一次,是2(2^1)的倍數的額外出現過一次,是4(2^2)的倍數的又額外出現一次,,,(這也恰恰是后綴0的意義)

在這里貼兩份按照上述兩種方法寫的代碼。

1 #include <bits/stdc++.h> 2 using namespace std; 3 4 typedef long long ll; 5 6 const ll MOD=1e9+7; 7 ll P[66]; 8 ll nP[66]; 9 ll a[101]; 10 ll arr[101]; 11 12 ll lowbit(ll x){ 13 ll low=x&(-x); 14 ll cnt=0; 15 while(low>>=1){ 16 cnt++; 17 } 18 return cnt; 19 } 20 21 void init(){ 22 P[0]=1;P[1]=2; 23 nP[0]=0;nP[1]=1; 24 for(int i=2;i<=62;++i){ 25 P[i]=2*P[i-1]; 26 nP[i]=P[i]-1; 27 } 28 29 //a[1]=1;a[2]=1; 30 //arr[1]=1;arr[2]=2; 31 //for(int i=3;i<101;i++){ 32 // a[i]=a[i-a[i-1]]+a[i-1-a[i-2]]; 33 // arr[i]=arr[i-1]+a[i]; 34 //} 35 36 //for(int i=1;i<101;++i) printf("%lld\n",arr[i]); 37 38 } 39 40 ll inv(ll a,ll m){ 41 if(a==1) return 1; 42 return inv(m%a,m)*(m-m/a)%m; 43 } 44 45 ll getbound(ll N){ 46 ll bound=0; 47 for(int i=62;i>=1;--i){ 48 while(N>=nP[i]){ 49 N-=nP[i]; 50 bound+=P[i-1]; 51 } 52 } 53 return bound; 54 } 55 56 int main(){ 57 //freopen("data.in","r",stdin); 58 //freopen("data1.out","w",stdout); 59 init(); 60 int T; 61 scanf("%d",&T); 62 while(T--){ 63 ll N; 64 scanf("%lld",&N); 65 if(N==1) puts("1"); 66 else{ 67 ll ans=0; 68 N-=1ll; 69 ll bound=0; 70 bound=getbound(N); 71 //printf("bound = %lld\n",bound); 72 ll cnt=lowbit(bound)+1ll; 73 ll tot=N; 74 for(ll i=1;i<=cnt;++i){ 75 if(bound==getbound(N+i)) tot++; 76 else break; 77 } 78 ll _m2=inv(2,MOD); 79 //printf("%lld\n",_m2); 80 for(int i=0;i<=62;++i){ 81 if(P[i]<=bound){ 82 ll M=bound/P[i]; 83 ans=(ans+(P[i]%MOD)*(M%MOD)%MOD*((M+1ll)%MOD)%MOD*_m2%MOD)%MOD; 84 } 85 else break; 86 } 87 //printf("1:%lld\n",(ans+1)%MOD); 88 ans=(ans-(bound)*(tot-N)%MOD+MOD)%MOD; 89 printf("%lld\n",(ans+1ll)%MOD); 90 //printf("%I64d %I64d\n",(ans+1ll)%MOD,arr[N+1]); 91 //最后加一 92 } 93 } 94 return 0; 95 } View Code 1 #include <bits/stdc++.h> 2 using namespace std; 3 4 typedef long long ll; 5 6 const ll MOD=1e9+7; 7 ll P[66]; 8 ll nP[66]; 9 ll a[101]; 10 ll arr[101]; 11 12 ll lowbit(ll x){ 13 ll low=x&(-x); 14 ll cnt=0; 15 while(low>>=1){ 16 cnt++; 17 } 18 return cnt; 19 } 20 21 void init(){ 22 P[0]=1;P[1]=2; 23 nP[0]=0;nP[1]=1; 24 for(int i=2;i<=62;++i){ 25 P[i]=2*P[i-1]; 26 nP[i]=P[i]-1; 27 } 28 29 //a[1]=1;a[2]=1; 30 //arr[1]=1;arr[2]=2; 31 //for(int i=3;i<101;i++){ 32 // a[i]=a[i-a[i-1]]+a[i-1-a[i-2]]; 33 // arr[i]=arr[i-1]+a[i]; 34 //} 35 36 //for(int i=1;i<101;++i) printf("%lld\n",arr[i]); 37 38 } 39 40 ll inv(ll a,ll m){ 41 if(a==1) return 1; 42 return inv(m%a,m)*(m-m/a)%m; 43 } 44 45 ll getbound(ll& N){ 46 ll bound=0; 47 for(int i=62;i>=1;--i){ 48 if(N>=nP[i]){ 49 N-=nP[i]; 50 bound+=P[i-1]; 51 } 52 } 53 return bound; 54 } 55 56 int main(){ 57 //freopen("data.in","r",stdin); 58 //freopen("data1.out","w",stdout); 59 init(); 60 int T; 61 scanf("%d",&T); 62 while(T--){ 63 ll N; 64 scanf("%lld",&N); 65 if(N==1) puts("1"); 66 else{ 67 ll ans=0; 68 N-=1ll; 69 ll bound=0; 70 bound=getbound(N); 71 //printf("bound = %lld\n",bound); 72 //ll cnt=lowbit(bound)+1ll; 73 //ll tot=N; 74 //for(ll i=1;i<=cnt;++i){ 75 // if(bound==getbound(N+i)) tot++; 76 // else break; 77 //} 78 ll _m2=inv(2,MOD); 79 for(int i=0;i<=62;++i){ 80 if(P[i]<=bound){ 81 ll M=bound/P[i]; 82 ans=(ans+(P[i]%MOD)*(M%MOD)%MOD*((M+1ll)%MOD)%MOD*_m2%MOD)%MOD; 83 84 } 85 else break; 86 } 87 //printf("1:%lld\n",(ans+1)%MOD); 88 ans=(ans+(bound+1)*N%MOD)%MOD; 89 printf("%lld\n",(ans+1ll)%MOD); 90 //printf("%I64d %I64d\n",(ans+1ll)%MOD,arr[N+1]); 91 //最后加一 92 } 93 } 94 return 0; 95 } View Code

然后,比賽時WA了兩發,其實規律找到了,但錯在了計算,算總和時,第一個錯誤處是沒用逆元,第二個錯誤處是P[i]在N為1e18時奇大,應該先mod在相乘。

血的教訓。

?

Chiaki is interested in an infinite sequence a1,a2,a3,..., which is defined as follows:
an={1an?an?1+an?1?an?2n=1,2n3
Chiaki would like to know the sum of the first n terms of the sequence, i.e. i=1nai. As this number may be very large, Chiaki is only interested in its remainder modulo (109+7).

轉載于:https://www.cnblogs.com/Kiritsugu/p/9363002.html

總結

以上是生活随笔為你收集整理的HDU 6304 Chiaki Sequence Revisited的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。