题目1 : 出勤记录I
略。
题目2 : 出勤记录II
题解:
dp【i】【0】表示最后一个是O的前i个可能的种类数
dp【i】【1】表示最后一个是L并且连续1次的前i个可能的种类数
dp【i】【2】表示最后一个是L并且连续2次的前i个可能的种类数
因为还要考虑没去的情况
那么最终答案就是
sum =E( ( sum + ans[i-1] * ans[N-i] % MOD ) % MOD; )
代码
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <map>
#include <queue>
using namespace std;
long long dp[110000][3];
long long ans[110000];
const long long MOD = 1e9+7;
int main(){
int N;
while( cin >> N ){
dp[1][0] = 1;
dp[1][1] = 1;
dp[1][2] = 0;
ans[1] = 2;
ans[0] = 1;
for( int i = 2; i <= N; i++ ){
dp[i][0] = ( ( dp[i-1][0] + dp[i-1][1] ) % MOD + dp[i-1][2] ) % MOD;
dp[i][1] = dp[i-1][0] % MOD;
dp[i][2] = dp[i-1][1] % MOD;
ans[i] = ( ( dp[i][0] + dp[i][1] ) % MOD + dp[i][2] ) % MOD;
}
long long sum = ans[N];
for( int i = 1; i <= N; i++ ){
sum = ( sum + ans[i-1] * ans[N-i] % MOD ) % MOD;
}
cout << sum << endl;
}
return 0;
}
题目3 : 区间价值
题解
思路是二分,然后cal(x)计算val比x大的区间的数量
cal里面的for循环,枚举左端点,然后利用hash来优化就行了
代码
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <map>
#include <queue>
using namespace std;
long long n;
long long k;
map<int,int> mp;
long long hashs[200005];
const int maxn=200005;
int arr[maxn];
int cnt[maxn];
long long cal(long long x){
long long ret=0;
memset(hashs,0,sizeof(hashs));
long long L=0,R=0,sum=0;
hashs[arr[0]]++;
for(int i=0;i<n;i++){
while(sum<x&&R<n){
R++;
if(R>=n) break;
sum+=hashs[arr[R]];
hashs[arr[R]]++;
}
if(sum>=x)
ret+=n-R;
hashs[arr[i]]--;
sum-=hashs[arr[i]];
}
return ret;
}
long long bs(long long a,long long b,long long val){
long long low=a,high=b;
long long ret=0;
while(low<=high){
long long mid=(low+high)/2;
if(cal(mid)<=val){
high=mid-1;
}
else{
low=mid+1;
}
}
return low-1;
}
int main()
{
int t;
cin>>t;
while(t--){
mp.clear();
cin>>n>>k;
for(int i=0;i<n;i++){
scanf("%d",&arr[i]);
mp[arr[i]]=1;
}
int idx=0;
for(map<int,int>::iterator it=mp.begin();it!=mp.end();it++)
it->second=idx++;
for(int i=0;i<n;i++){
arr[i]=mp[arr[i]];
}
cout<<bs(0,n*(n-1)/2,n*(n+1)/2-k)<<endl;
}
return 0;
}
/*
2
4 7
1 1 2 3
3 6
100 100 100
*/
题目4 : 手势识别
题解
dp【st】【i】表示组合了st中的图形,并且最后一个图形是第i个的最小权值。
然后最后判断一下st就好了。
有一点要注意,在输入的时候要把那种长的线段分解成小的线段(比如(1,1)->(4,4) 分解成 (1,1)->(2,2)->(3,3)->(4,4))
代码
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <map>
#include <queue>
using namespace std;
struct Node{
int x, y;
bool operator==(const Node b )const{
return x == b.x && y == b.y;
}
};
int dp[1<<18][20];
int mark[1<<18];
int N, M, weight[20], cnt[20];
bool g[20][5][5][5][5];
bool tempmark[5][5][5][5];
Node node[20][2];
int judge( int st ){
// cout << tempmark[3][4][4][3] << endl;
if( mark[st] != -1 ){
return mark[st];
}
bool t[5][5][5][5];
memset( t, false, sizeof( t ) );
int ss = 0;
for( int i = 0; i < N; i++ ){
if( st & ( 1 << i ) ){
for( int j = 1; j <= 4; j++ ){
for( int k = 1; k <= 4; k++ ){
for( int p = 1; p <= 4; p++ ){
for( int q = 1; q <= 4; q++ ){
t[j][k][p][q] |= g[i][j][k][p][q];
}
}
}
}
}
}
// bool flag = true;
for( int j = 1; j <= 4; j++ ){
for( int k = 1; k <= 4; k++ ){
for( int p = 1; p <= 4; p++ ){
for( int q = 1; q <= 4; q++ ){
// if( j == 3 && k == 4 && p == 4 && q == 3 ){
// cout << t[j][k][p][k] << endl;
// cout << tempmark[j][k][p][k] <<endl;
// cout << tempmark[3][4][4][3] << endl;
// int ttt = temp[j][k][p]
// }
if( t[j][k][p][q] != tempmark[j][k][p][q] ){
return mark[st] = 0;
}
}
}
}
}
return mark[st] = 1;
}
Node dealnode[300];
int deal( Node node1, Node node2 ){
int sum = 0;
for( int i = 1; i <= 4; i++ ){
for( int j = 1; j <= 4; j++ ){
if( i < min( node1.x, node2.x ) || i > max( node1.x, node2.x ) ) continue;
if( j < min( node1.y, node2.y ) || j > max( node1.y, node2.y ) ) continue;
if( ( j - node1.y ) * ( node2.x - i ) == ( node2.y - j ) * ( i - node1.x) ){
dealnode[sum].x = i;
dealnode[sum++].y = j;
}
}
}
return sum;
}
int main(){
while( scanf( "%d", &N ) != EOF ){
memset( g, false, sizeof( g ) );
for( int i = 0; i < N; i++ ){
scanf( "%d%d", &cnt[i], &weight[i] );
Node tp[300];
for( int j = 0; j < cnt[i]; j++ ){
scanf( "%d%d", &tp[j].x, &tp[j].y );
}
node[i][0] = tp[0];
node[i][1] = tp[cnt[i]-1];
for( int j = 1; j < cnt[i]; j++ ){
int t = deal( tp[j], tp[j-1] );
for( int k = 0; k < t; k++ ){
for( int l = k + 1; l < t; l++ ){
// if( abs( dealnode[k].x - dealnode[l].x ) >= 2 ) continue;
// if( abs( dealnode[k].y - dealnode[l].y ) >= 2 ) continue;
// g[i][dealnode[k].x][dealnode[k].y][dealnode[l].x][dealnode[l].y] = true;
// g[i][dealnode[l].x][dealnode[l].y][dealnode[k].x][dealnode[k].y] = true;
if( dealnode[k].x == dealnode[l].x || dealnode[k].y == dealnode[l].y || abs( dealnode[k].x - dealnode[l].x ) == abs( dealnode[k].y - dealnode[l].y ) ){
if( abs( dealnode[k].x - dealnode[l].x ) >= 2 ) continue;
if( abs( dealnode[k].y - dealnode[l].y ) >= 2 ) continue;
g[i][dealnode[k].x][dealnode[k].y][dealnode[l].x][dealnode[l].y] = true;
g[i][dealnode[l].x][dealnode[l].y][dealnode[k].x][dealnode[k].y] = true;
}else{
g[i][dealnode[k].x][dealnode[k].y][dealnode[l].x][dealnode[l].y] = true;
g[i][dealnode[l].x][dealnode[l].y][dealnode[k].x][dealnode[k].y] = true;
}
}
}
}
}
scanf( "%d", &M );
memset( tempmark, false, sizeof( tempmark ) );
for( int i = 0; i < M; i++ ){
Node a, b;
scanf( "%d%d%d%d", &a.x, &a.y, &b.x, &b.y );
int t = deal(a,b);
for( int k = 0; k < t; k++ ){
for( int l = k + 1; l < t; l++ ){
if( dealnode[k].x == dealnode[l].x || dealnode[k].y == dealnode[l].y || abs( dealnode[k].x - dealnode[l].x ) == abs( dealnode[k].y - dealnode[l].y ) ){
if( abs( dealnode[k].x - dealnode[l].x ) >= 2 ) continue;
if( abs( dealnode[k].y - dealnode[l].y ) >= 2 ) continue;
tempmark[dealnode[k].x][dealnode[k].y][dealnode[l].x][dealnode[l].y] = true;
tempmark[dealnode[l].x][dealnode[l].y][dealnode[k].x][dealnode[k].y] = true;
}else{
tempmark[dealnode[k].x][dealnode[k].y][dealnode[l].x][dealnode[l].y] = true;
tempmark[dealnode[l].x][dealnode[l].y][dealnode[k].x][dealnode[k].y] = true;
}
}
}
}
memset( mark, -1, sizeof( mark ) );
memset( dp, 0x3f, sizeof( dp ) );
for( int i = 0; i < N; i++ ){
dp[1<<i][i] = weight[i];
}
for( int st = 0; st < ( 1 << N ); st++ ){
for( int i = 0; i < N; i++ ){
if( dp[st][i] == -1 ) continue;
if( !(st & ( 1 << i ) ) ) continue;
for( int j = 0; j < N; j++ ){
if( ( 1 << j ) & st ) continue;
if( node[i][1] == node[j][0] ){
dp[st|(1<<j)][j] = min( dp[st|(1<<j)][j], dp[st][i] + weight[j] );
}
}
}
}
int ans = 1e9;
for( int st = 0; st < ( 1 << N ); st++ ){
if( judge(st) == 0 ) continue;
for( int i = 0; i < N; i++ ){
if( !(st & ( 1 << i ) ) ) continue;
ans = min( ans, dp[st][i] );
}
}
cout << ans << endl;
}
return 0;
}
/*
3
2 1 1 1 2 2
2 1 2 2 3 3
2 1 1 1 3 3
1
1 1 3 3
1
7 1 2 2 3 3 2 4 1 2 2 1 4 2 3 4
12
2 2 3 3
3 3 2 4
2 4 1 2
1 2 2 1
2 1 4 2
4 2 3 4
3 4 4 3
4 3 3 1
3 1 1 3
1 3 2 4
2 4 3 3
3 3 1 2
*/