小数据跑网络流,
得到答案如下:
NN=2 flow=1
NN=3 flow=3 2
NN=4 flow=5 2
NN=5 flow=10 5
NN=6 flow=12 2
NN=7 flow=17 5
NN=8 flow=19 2
NN=9 flow=36 17
NN=10 flow=38 2
NN=11 flow=43 5
NN=12 flow=45 2
NN=13 flow=62 17
NN=14 flow=64 2
NN=15 flow=69 5
NN=16 flow=71 2
NN=17 flow=136 65
NN=18 flow=138 2
NN=19 flow=143 5
NN=20 flow=145 2
NN=21 flow=162 17
NN=22 flow=164 2
NN=23 flow=169 5
NN=24 flow=171 2
NN=25 flow=236 65
NN=26 flow=238 2
NN=27 flow=243 5
NN=28 flow=245 2
NN=29 flow=262 17
NN=30 flow=264 2
NN=31 flow=269 5
NN=32 flow=271 2
NN=33 flow=528 257
NN=34 flow=530 2
NN=35 flow=535 5
NN=36 flow=537 2
NN=37 flow=554 17
NN=38 flow=556 2
NN=39 flow=561 5
NN=40 flow=563 2
NN=41 flow=628 65
NN=42 flow=630 2
NN=43 flow=635 5
NN=44 flow=637 2
NN=45 flow=654 17
NN=46 flow=656 2
NN=47 flow=661 5
NN=48 flow=663 2
NN=49 flow=920 257
NN=50 flow=922 2
NN=51 flow=927 5
NN=52 flow=929 2
NN=53 flow=946 17
NN=54 flow=948 2
NN=55 flow=953 5
NN=56 flow=955 2
NN=57 flow=1020 65
NN=58 flow=1022 2
NN=59 flow=1027 5
NN=60 flow=1029 2
NN=61 flow=1046 17
NN=62 flow=1048 2
NN=63 flow=1053 5
NN=64 flow=1055 2
NN=65 flow=2080 1025
NN=66 flow=2082 2
NN=67 flow=2087 5
NN=68 flow=2089 2
NN=69 flow=2106 17
NN=70 flow=2108 2
观察答案的增量,存在一定的规律。
将之分组,规律比较明显:
2
2 5
2 5 2 17
2 5 2 17 2 5 2 65
2 5 2 17 2 5 2 65 2 5 2 17 2 5 2 257
…
在第一组中,只有一个2;
第二组中,每2个数出现一个5;
第三组中,每2个数出现一个5,每4个数出现一个17;
第四组中,每2个数出现一个5,每4个数出现一个17,每8个数出现一个65;
第五组中,每2个数出现一个5,每4个数出现一个17,每8个数出现一个65,每16个数出现一个257;
2=2^0+1, 5=2^2+1, 17=2^4+1, 257=2^8+1;
代码如下:
#include<cmath>
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
#define debug puts("Infinity is awesome!")
#define mm(a, b) memset(a, b, sizeof(a))
#define LL long long
using namespace std;
const int maxn=1e3+5;
const LL mod=1e9+7;
const double eps=1e-8;
LL f[maxn];
void Pre(){
f[0]=1LL;
for(int i=1;i<200;i++)
f[i]=(f[i-1]<<1)%mod;
}
int main(){
int T;
int cas=0;
LL n;
Pre();
while(~scanf("%lld", &n)){
n--;
if(n==1){printf("1\n"); continue;}
LL ans=1; n--;
for(int i=0;i<64&&n>0;i++){
LL cnt=(n>>i)%mod;
LL tmp=(f[2*i]+1)%mod;
ans=(ans+cnt*tmp%mod)%mod;
if(i){
tmp=(f[2*(i-1)]+1)%mod;
ans=(ans-cnt*tmp%mod+mod)%mod;
}
n-=(1LL<<i);
}
printf("%lld\n", ans);
}
return 0;
//今天完全挂机态,对不起队友。
}