启智树提高组day4T3 T3(t3.cpp,1s,512MB)

启智树提高组day4T3 T3(t3.cpp,1s,512MB)

题面描述

 

 

 输入格式

输出格式

 

 

样例输入

样例输出

数据范围

 

 

题解

 task1

暴力dfs

10分

Code

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<cstdio>
 4 #include<cstring>
 5 #include<cmath>
 6 #include<map>
 7 #include<set>
 8 #include<queue>
 9 #include<vector>
10 #define IL inline
11 #define re register
12 #define LL long long
13 #define ULL unsigned long long
14 using namespace std;
15 //1e1
16 template<class T>inline void read(T&x)
17 {
18     char ch=getchar();
19     while(!isdigit(ch))ch=getchar();
20     x=ch-'0';ch=getchar();
21     while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
22 }
23 int G[55];
24 template<class T>inline void write(T x)
25 
26 {
27     int g=0;
28     do{G[++g]=x%10;x/=10;}while(x);
29     for(int i=g;i>=1;--i)putchar('0'+G[i]);putchar('\n');
30 }
31 const ULL M = 1e9+7;
32 ULL range[64]={1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768,65536,131072,262144,524288,1048576,2097152,4194304,8388608,16777216,33554432,67108864,134217728,268435456,536870912,1073741824,2147483648,4294967296,8589934592,17179869184,34359738368,68719476736,137438953472,274877906944,549755813888,1099511627776,2199023255552,4398046511104,8796093022208,17592186044416,35184372088832,70368744177664,140737488355328,281474976710656,562949953421312,1125899906842624,2251799813685248,4503599627370496,9007199254740992,18014398509481984,36028797018963968,72057594037927936,144115188075855872,288230376151711744,576460752303423488,1152921504606846976,2305843009213693952,4611686018427387904,9223372036854775808};
33 ULL dfs(ULL num,ULL now)
34 {
35     if(num==0) return 1;
36     ULL ans=0;
37     for(int i=now;i>=0;i--)
38     {
39         if(range[i]>num) continue;
40 //        cout<<"dfs"<<i<<endl;
41         ans+=dfs(num-range[i],i);
42     }
43     return ans%M;
44 }
45 
46 ULL n,T;
47 int main()
48 {
49     cin>>T;
50     while(T--)
51     {
52         read(n);
53         write(dfs(n,64)%M);
54     }
55     
56     return 0;
57 }
View Code

task2

加入记忆化(先用map)

Code

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<cstdio>
 4 #include<cstring>
 5 #include<cmath>
 6 #include<map>
 7 #include<set>
 8 #include<queue>
 9 #include<vector>
10 #define IL inline
11 #define re register
12 #define LL long long
13 #define ULL unsigned long long
14 using namespace std;
15 //1e5
16 template<class T>inline void read(T&x)
17 {
18     char ch=getchar();
19     while(!isdigit(ch))ch=getchar();
20     x=ch-'0';ch=getchar();
21     while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
22 }
23 int G[55];
24 template<class T>inline void write(T x)
25 {
26     int g=0;
27     do{G[++g]=x%10;x/=10;}while(x);
28     for(int i=g;i>=1;--i)putchar('0'+G[i]);putchar('\n');
29 }
30 const ULL M = 1e9+7;
31 ULL range[64]={1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768,65536,131072,262144,524288,1048576,2097152,4194304,8388608,16777216,33554432,67108864,134217728,268435456,536870912,1073741824,2147483648,4294967296,8589934592,17179869184,34359738368,68719476736,137438953472,274877906944,549755813888,1099511627776,2199023255552,4398046511104,8796093022208,17592186044416,35184372088832,70368744177664,140737488355328,281474976710656,562949953421312,1125899906842624,2251799813685248,4503599627370496,9007199254740992,18014398509481984,36028797018963968,72057594037927936,144115188075855872,288230376151711744,576460752303423488,1152921504606846976,2305843009213693952,4611686018427387904,9223372036854775808};
32 struct Pair{
33     ULL a,b;
34     
35 };
36 bool operator<(Pair y,Pair x){
37     return (y.a==x.a)?y.b<x.b:y.a<x.a; 
38 }
39 map<Pair,ULL>his; 
40 ULL dfs(ULL num,ULL now)
41 {
42     if(num==0) return 1;
43     if(his.find({num,now})!=his.end()) return his[{num,now}];
44     ULL ans=0;
45     for(int i=now;i>=0;i--)
46     {
47         if(range[i]>num) continue;
48 //        cout<<"dfs"<<i<<endl;
49         ans+=dfs(num-range[i],i);
50     }
51     return his[{num,now}]=ans%M;
52 }
53 
54 ULL n,T;
55 int main()
56 {
57     cin>>T;
58     while(T--)
59     {
60         read(n);
61         write(dfs(n,64)%M);
62     }
63     return 0;
64 }
View Code

task3

不幸的是,刚刚两种方法都只有10分!!!

通过用task2打表发现

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<cstdio>
 4 #include<cstring>
 5 #include<cmath>
 6 #include<map>
 7 #include<set>
 8 #include<queue>
 9 #include<vector>
10 #define IL inline
11 #define re register
12 #define LL long long
13 #define ULL unsigned long long
14 using namespace std;
15 //1e5
16 template<class T>inline void read(T&x)
17 {
18     char ch=getchar();
19     while(!isdigit(ch))ch=getchar();
20     x=ch-'0';ch=getchar();
21     while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
22 }
23 int G[55];
24 template<class T>inline void write(T x)
25 {
26     int g=0;
27     do{G[++g]=x%10;x/=10;}while(x);
28     for(int i=g;i>=1;--i)putchar('0'+G[i]);putchar('\n');
29 }
30 const ULL M = 1e9+7;
31 ULL range[64]={1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768,65536,131072,262144,524288,1048576,2097152,4194304,8388608,16777216,33554432,67108864,134217728,268435456,536870912,1073741824,2147483648,4294967296,8589934592,17179869184,34359738368,68719476736,137438953472,274877906944,549755813888,1099511627776,2199023255552,4398046511104,8796093022208,17592186044416,35184372088832,70368744177664,140737488355328,281474976710656,562949953421312,1125899906842624,2251799813685248,4503599627370496,9007199254740992,18014398509481984,36028797018963968,72057594037927936,144115188075855872,288230376151711744,576460752303423488,1152921504606846976,2305843009213693952,4611686018427387904,9223372036854775808};
32 struct Pair{
33     ULL a,b;
34     
35 };
36 bool operator<(Pair y,Pair x){
37     return (y.a==x.a)?y.b<x.b:y.a<x.a; 
38 }
39 map<Pair,ULL>his; 
40 ULL dfs(ULL num,ULL now)
41 {
42     if(num==0) return 1;
43     if(his.find({num,now})!=his.end()) return his[{num,now}];
44     ULL ans=0;
45     for(int i=now;i>=0;i--)
46     {
47         if(range[i]>num) continue;
48 //        cout<<"dfs"<<i<<endl;
49         ans+=dfs(num-range[i],i);
50     }
51     return his[{num,now}]=ans%M;
52 }
53 
54 ULL n,T,t;
55 int main()
56 {
57     cin>>T;
58     for(int i=1;i<=T;i++) cout<<i<<"\t"<<dfs(i,64)<<"\t"<<dfs(i,64)-n<<endl,n=dfs(i,64);
59     return 0;
60 }
记忆化打表
  1. 第i个和第i-1个的值相同(当i>1且i为奇数的时候)
  2. f[i]=f[i/2]+f[i-1]

差分一下就可以发现规律

http://oeis.org/search?q=1%2C2%2C4%2C6%2C10%2C14%2C20%2C26&sort=&language=english&go=Search

在OEIS上也能搜到

http://oeis.org/A000123

但是上面也只有这个式子

这里就可以用记忆化+打表,大概可以做出10^9

Code

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<cstdio>
 4 #include<cstring>
 5 #include<cmath>
 6 #include<map>
 7 #include<set>
 8 #include<queue>
 9 #include<vector>
10 #define IL inline
11 #define re register
12 #define LL long long
13 #define ULL unsigned long long
14 using namespace std;
15 //1e5
16 template<class T>inline void read(T&x)
17 {
18     char ch=getchar();
19     while(!isdigit(ch))ch=getchar();
20     x=ch-'0';ch=getchar();
21     while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
22 }
23 int G[55];
24 template<class T>inline void write(T x)
25 {
26     int g=0;
27     do{G[++g]=x%10;x/=10;}while(x);
28     for(int i=g;i>=1;--i)putchar('0'+G[i]);putchar('\n');
29 }
30 const ULL M = 1e9+7;
31 //ULL range[63]={1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768,65536,131072,262144,524288,1048576,2097152,4194304,8388608,16777216,33554432,67108864,134217728,268435456,536870912,1073741824,2147483648,4294967296,8589934592,17179869184,34359738368,68719476736,137438953472,274877906944,549755813888,1099511627776,2199023255552,4398046511104,8796093022208,17592186044416,35184372088832,70368744177664,140737488355328,281474976710656,562949953421312,1125899906842624,2251799813685248,4503599627370496,9007199254740992,18014398509481984,36028797018963968,72057594037927936,144115188075855872,288230376151711744,576460752303423488,1152921504606846976,2305843009213693952,4611686018427387904};
32 struct Pair{
33     ULL a,b;
34     
35 };
36 bool operator<(Pair y,Pair x){
37     return (y.a==x.a)?y.b<x.b:y.a<x.a; 
38 }
39 map<ULL,ULL>his; 
40 ULL dfs(ULL num)
41 {
42     if(num==0) return 1;
43     if(num&1&&num>1) return dfs(num-1);
44     if(his.find(num)!=his.end()) return his[num];
45     ULL ans=0;
46     ans=dfs(num/2)+dfs(num-1);
47     return his[num]=ans%M;
48 }
49 
50 ULL n,T;
51 int main()
52 {
53     cin>>T;
54     his[1]=1;
55     his[2]=2;
56     while(T--)
57     {
58         read(n);
59         write(dfs(n)%M);
60     }
61     return 0;
62 }
记忆化打表

Std

 

Code

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 using ll=long long;
 4 const ll mod=1e9+7;
 5 int T;
 6 ll n,f[70][70],g[70][70],S[70][70],S1[70][70];
 7 ll po(ll a,ll b){ll r=1;for(;b;b/=2,a=a*a%mod)if(b&1)r=r*a%mod;return r;}
 8 ll solve(int x,int k){
 9     if(!(n>>x))return k?0:1;
10     if(f[x][k]>-1e18)return f[x][k];
11     ll res=0,t=1;
12     for(int i=0;i<=k+1;i++)(res+=g[k][i]*t)%=mod,(t*=((n>>x)+1)%mod)%=mod;
13     (res*=solve(x+1,0))%=mod;t=1;
14     for(int i=0;i<=k+1;i++)(res-=solve(x+1,i)*g[k][i]%mod*t)%=mod,(t*=2)%=mod;
15     return f[x][k]=res;
16 }
17 int main(){
18     scanf("%d",&T);
19     for(int i=0;i<70;i++){
20         S[i][0]=S1[i][0]=!i;
21         for(int j=1;j<=i;j++)
22             S[i][j]=(S[i-1][j-1]+j*S[i-1][j])%mod,
23             S1[i][j]=(S1[i-1][j-1]+(i-1)*S1[i-1][j])%mod;
24     }
25     for(int k=0;k<=64;k++)
26         for(int j=0;j<=k;j++){
27             ll cf=S[k][j]*po(j+1,mod-2)%mod;
28             for(int i=0;i<=j+1;i++)(g[k][i]+=cf*S1[j+1][i]*(j+i&1?1:-1))%=mod;
29         }
30     while(T--){
31         scanf("%lld",&n);
32         memset(f,192,sizeof f);
33         printf("%lld\n",(solve(1,0)+mod)%mod);
34 
35     }
36     return 0;
37 }

小结

别等黄花菜都凉了才——

别等服务器都炸了才交代码

 

posted @ 2020-08-20 13:13  Vanilla_chan  阅读(269)  评论(0编辑  收藏  举报