单链dp很好想
成环就比较难搞了
可以将单链dp改进一下
dp[i][0]表示首尾不同的长度为i的单链有多少种情况
dp[i][1]表示首尾相同的长度为i的单链有多少种情况
那么成环就可以用容斥定理瞎搞了
Talk is cheap, show me the code.
#include <cstdio>
#include <algorithm>
#define MAXN 100000
#define MOD 2015
using namespace std;
int dp[MAXN + 5][3], ans[MAXN + 5];
void solve(){
dp[1][0] = 0, dp[1][1] = 2;;
for(int i = 2; i <= 6; i++) dp[i][0] = dp[i][1] = (1 << (i - 1));
dp[7][0] = (1 << 6), dp[7][1] = (1 << 6) - 2;
for(int i = 8; i <= MAXN; i++){
dp[i][0] = (dp[i-1][1] + dp[i-1][0] - dp[i-7][1] + MOD) % MOD;
dp[i][1] = (dp[i-1][0] + dp[i-1][1] - dp[i-7][0] + MOD) % MOD;
}
for(int i = 1; i <= 7; i++) ans[i] = dp[i][0] + dp[i][1];
for(int i = 8; i <= MAXN; i++){
for(int j = 0; j < 6 ; j++) ans[i] = (ans[i] + dp[i-j][0]) % MOD;
for(int j = 1; j <= 5; j++)
for(int k = 0; k < min(j, i - 7); k++) ans[i] = (ans[i] - dp[i-7-k][1] + MOD) % MOD;
}
}
int main(){
solve();
int T, n, Case = 0;
scanf("%d", &T);
while(T--){
scanf("%d", &n);
printf("Case #%d: %d\n", ++Case, ans[n]);
}
return 0;
}