質問編集履歴

6

2019/05/14 00:51

投稿

toshiyan
toshiyan

スコア74

test CHANGED
File without changes
test CHANGED
File without changes

5

intをlong longに

2019/05/14 00:51

投稿

toshiyan
toshiyan

スコア74

test CHANGED
File without changes
test CHANGED
@@ -94,7 +94,7 @@
94
94
 
95
95
  int k=0;
96
96
 
97
- int kk=K;
97
+ long long kk=K;
98
98
 
99
99
  while(kk)k++,kk>>=1;
100
100
 

4

微妙な言い間違いの修正

2019/05/13 10:18

投稿

toshiyan
toshiyan

スコア74

test CHANGED
File without changes
test CHANGED
@@ -156,7 +156,7 @@
156
156
 
157
157
 
158
158
 
159
- しかしこのコードでは、数列の要素がKを超えた場合が考慮されていません。
159
+ しかしこのコードでは、数列の最後の要素がKを超えた場合が考慮されていません。
160
160
 
161
161
  たとえばN=3、K=2のとき、(1, 2, 3), (2, 1, 3)まで数えてしまうため、出力は5です。
162
162
 

3

行間

2019/05/13 10:11

投稿

toshiyan
toshiyan

スコア74

test CHANGED
File without changes
test CHANGED
@@ -161,3 +161,15 @@
161
161
  たとえばN=3、K=2のとき、(1, 2, 3), (2, 1, 3)まで数えてしまうため、出力は5です。
162
162
 
163
163
  どのように書き換えれば __数列の要素がKを超えた場合__ を考慮できるかわからず、解決の糸口が見つからなかったため質問いたしました。
164
+
165
+
166
+
167
+ ## 追記2
168
+
169
+
170
+
171
+ できればヒントだけでも教えていただけると嬉しいです。
172
+
173
+ ある程度の行間であれば頑張って対応いたします。
174
+
175
+ 回答よろしくお願いします。

2

2^50の制約が無考慮

2019/05/13 09:50

投稿

toshiyan
toshiyan

スコア74

test CHANGED
File without changes
test CHANGED
@@ -58,7 +58,7 @@
58
58
 
59
59
 
60
60
 
61
- int dp[50][2];
61
+ int dp[52][2];
62
62
 
63
63
 
64
64
 

1

考えたこと追記

2019/05/13 09:44

投稿

toshiyan
toshiyan

スコア74

test CHANGED
File without changes
test CHANGED
@@ -11,3 +11,153 @@
11
11
 
12
12
 
13
13
  という問題を解きたいのですが、解くことができません。どのようにすれば解けるでしょうか?制約は N ≦ 1000, K ≦ 2^50 です。
14
+
15
+
16
+
17
+ ## 追記
18
+
19
+
20
+
21
+ 考えたことを追記します。
22
+
23
+
24
+
25
+ ①__長さNのK以下の数列のXORが0の通り数__ (求めたいもの)
26
+
27
+ ②__長さN-1のK以下の数列のXORがK以下の通り数__
28
+
29
+ ③__長さN-1のK以下の数列のXORがKを超える通り数__
30
+
31
+
32
+
33
+ ①と②は等しいです。
34
+
35
+ なぜなら、②のXORの結果と同じ数値を後ろに付け足せば、①の数列になるからです。
36
+
37
+ そして、③は②の余事象であるため、③を求めることを考えました。
38
+
39
+ 以下のようなDPを考えます。
40
+
41
+
42
+
43
+ dp[i][j] := 上からiビット目まで見たときの通り数(jはKを超えたかどうか)
44
+
45
+
46
+
47
+ そして次のようなコードを書きました。
48
+
49
+ (オーバーフローは気にしない方向でお願いします)
50
+
51
+
52
+
53
+ ```cpp
54
+
55
+ #include <bits/stdc++.h>
56
+
57
+ using namespace std;
58
+
59
+
60
+
61
+ int dp[50][2];
62
+
63
+
64
+
65
+ int comb(int x,int y){
66
+
67
+ if(x<0||y<0||x<y)return 0;
68
+
69
+ int r=1;
70
+
71
+ for(int i=1;i<=y;++i){
72
+
73
+ r*=(x-i+1);
74
+
75
+ r/=i;
76
+
77
+ }
78
+
79
+ return r;
80
+
81
+ }
82
+
83
+
84
+
85
+ int main(){
86
+
87
+ int N;
88
+
89
+ long long K;
90
+
91
+ cin>>N>>K;
92
+
93
+
94
+
95
+ int k=0;
96
+
97
+ int kk=K;
98
+
99
+ while(kk)k++,kk>>=1;
100
+
101
+
102
+
103
+ int odd=0,even=0;
104
+
105
+ for(int i=1;i<=N-1;i+=2){
106
+
107
+ odd+=comb(N-1,i);
108
+
109
+ }
110
+
111
+ for(int i=0;i<=N-1;i+=2){
112
+
113
+ even+=comb(N-1,i);
114
+
115
+ }
116
+
117
+
118
+
119
+ dp[0][0]=1;
120
+
121
+ for(int i=0;i<k;++i){
122
+
123
+ for(int j=0;j<=1;++j){
124
+
125
+ if(j==1){
126
+
127
+ dp[i+1][j]+=dp[i][j]*(even+odd);
128
+
129
+ }else{
130
+
131
+ if((K&(1LL<<(k-i-1)))==0){
132
+
133
+ dp[i+1][1]+=dp[i][j]*odd;
134
+
135
+ dp[i+1][0]+=dp[i][j]*even;
136
+
137
+ }else{
138
+
139
+ dp[i+1][j]+=dp[i][j]*odd;
140
+
141
+ }
142
+
143
+ }
144
+
145
+ }
146
+
147
+ }
148
+
149
+ cout<<pow(K+1,N-1)-dp[k][1]<<endl;
150
+
151
+ return 0;
152
+
153
+ }
154
+
155
+ ```
156
+
157
+
158
+
159
+ しかしこのコードでは、数列の要素がKを超えた場合が考慮されていません。
160
+
161
+ たとえばN=3、K=2のとき、(1, 2, 3), (2, 1, 3)まで数えてしまうため、出力は5です。
162
+
163
+ どのように書き換えれば __数列の要素がKを超えた場合__ を考慮できるかわからず、解決の糸口が見つからなかったため質問いたしました。