1.路径计数
题目解析
动态规划, d p [ i ] [ j ] dp[i][j] dp[i][j]为到达第i行第j列的方案数
代码
#include <bits/stdc++.h>
using namespace std;
int n,mp[101][101],dp[101][101];
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;++i)
for(int j=1;j<=n;++j)
scanf("%d",&mp[i][j]);
for(int i=1;i<=n;++i)
{
for(int j=1;j<=n;++j)
{
if(i==1&&j==1)
dp[i][j]=1;
else if(i==1)
{
if(mp[i][j-1]==1)
{
dp[i][j]+=dp[i][j-1];
dp[i][j]%=1000000007;
}
}
else if(j==1)
{
if(mp[i-1][j]==1)
{
dp[i][j]+=dp[i-1][j];
dp[i][j]%=1000000007;
}
}
else
{
if(mp[i][j-1]==1)
{
dp[i][j]+=dp[i][j-1];
dp[i][j]%=1000000007;
}
if(mp[i-1][j]==1)
{
dp[i][j]+=dp[i-1][j];
dp[i][j]%=1000000007;
}
}
}
}
cout<<dp[n][n]<<endl;
return 0;
}
2.最大和上升子序列
题目解析
动态规划, d p [ i ] dp[i] dp[i]指的是以 a [ i ] a[i] a[i]结尾的最大和上升子序列
代码
#include <bits/stdc++.h>
using namespace std;
int n,a[1001],dp[1001],ans;
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;++i)
scanf("%d",&a[i]);
for(int i=1;i<=n;++i)
{
dp[i]=a[i];
for(int j=i-1;j>=1;--j)
{
if(a[j]<a[i])
dp[i]=max(dp[i],a[i]+dp[j]);
}
ans=max(ans,dp[i]);
}
cout<<ans<<endl;
return 0;
}
3.加一
题目解析
动态规划,输入的数字每一位都可以独立计算,
d
p
[
i
]
[
j
]
dp[i][j]
dp[i][j]为数字
j
j
j经过
i
i
i次操作后的位数。
0
<
=
j
<
=
9
0<=j<=9
0<=j<=9。
d
p
[
i
]
[
9
]
dp[i][9]
dp[i][9]少操作一次可转化为
d
p
[
i
−
1
]
[
0
]
dp[i-1][0]
dp[i−1][0]和
d
p
[
i
−
1
]
[
1
]
dp[i-1][1]
dp[i−1][1]。
d
p
[
i
]
[
9
]
=
d
p
[
i
−
1
]
[
0
]
+
d
p
[
i
−
1
]
[
1
]
dp[i][9]=dp[i-1][0]+dp[i-1][1]
dp[i][9]=dp[i−1][0]+dp[i−1][1]。
其余
d
p
[
i
]
[
j
]
dp[i][j]
dp[i][j]少操作一次可转化为
d
p
[
i
−
1
]
[
j
+
1
]
dp[i-1][j+1]
dp[i−1][j+1]。
d
p
[
i
]
[
j
]
=
d
p
[
i
−
1
]
[
j
+
1
]
dp[i][j]=dp[i-1][j+1]
dp[i][j]=dp[i−1][j+1]。
代码
#include <bits/stdc++.h>
using namespace std;
int T,n,m,s=-1;
int mod=1e9+7;
int dp[200001][10];
int main()
{
scanf("%d",&T);
while(T--)
{
scanf("%d %d",&n,&m);
if(s<m)
{
for(int i=s+1;i<=m;++i)
{
for(int j=0;j<10;++j)
{
if(i==0)
dp[i][j]=1;
else
{
if(j==9)
dp[i][9]=(dp[i-1][0]+dp[i-1][1])%mod;
else
dp[i][j]=(dp[i-1][j+1])%mod;
}
}
}
s=m;
}
int ans=0;
while(n)
{
ans+=dp[m][n%10];
ans%=mod;
n/=10;
}
printf("%d\n",ans);
}
return 0;
}
4.跳跳
代码
#include <bits/stdc++.h>
using namespace std;
int N,x,y;
set<pair<int,int> > m;
vector<pair<int,int> > v;
int main()
{
scanf("%d",&N);
for(int i=1;i<=N;++i)
{
scanf("%d %d",&x,&y);
v.push_back(make_pair(x,y));
}
for(int i=0;i<N;++i)
{
for(int j=0;j<N;++j)
{
if(j!=i)
{
int a=v[j].first-v[i].first;
int b=v[j].second-v[i].second;
if(a!=0&&b!=0)
{
int num=__gcd(abs(a),abs(b));
a/=num;
b/=num;
if(m.find(make_pair(a,b))==m.end())
m.insert(make_pair(a,b));
}
else if(a==0)
{
b=(b>0?1:-1);
if(m.find(make_pair(a,b))==m.end())
m.insert(make_pair(a,b));
}
else if(b==0)
{
a=(a>0?1:-1);
if(m.find(make_pair(a,b))==m.end())
m.insert(make_pair(a,b));
}
}
}
}
cout<<m.size()<<endl;
return 0;
}
5.异或和或
题目解析
1^1=0 1||1=1
1^0=1 1||0=1
0^0=1 0||0=0
如果s上有1,与t上对应位置的数字相同,那么s可以改成t
如果s上有1和0, 与t上对应位置的数字不同,那么s可以改成t
代码
#include <bits/stdc++.h>
using namespace std;
int T;
string s, t;
int main()
{
scanf("%d", &T);
while (T--)
{
cin >> s >> t;
if (s == t)
{
printf("YES\n");
continue;
}
if (s.length() != t.length() || s.length() == 1)
{
printf("NO\n");
continue;
}
bool flag1=false,flag2=false,flag3=false;
for (int i = 0; i < s.length(); ++i)
{
if(s[i]==t[i]&&s[i]=='1')
flag1=true;
else if(s[i]!=t[i]&&s[i]=='1')
flag2=true;
else if(s[i]!=t[i]&&s[i]=='0')
flag3=true;
if(flag1||(flag2&&flag3))
{
printf("YES\n");
break;
}
if(i==s.length()-1)
printf("NO\n");
}
}
return 0;
}
6.01序列
题目解析
前缀和,
f
[
i
]
f[i]
f[i]为到
i
i
i这个位置1的数量,
c
n
t
[
i
]
cnt[i]
cnt[i]为含1数量为
i
i
i的序列数。
所有前缀和为
x
x
x的序列都可以和前缀和为
x
−
k
x-k
x−k的序列组成子串(
x
−
k
x-k
x−k到
x
x
x之间有k个1),所以
a
n
s
+
=
c
n
t
[
i
]
∗
c
n
t
[
i
−
k
]
ans += cnt[i] * cnt[i - k]
ans+=cnt[i]∗cnt[i−k]。
代码
#include <bits/stdc++.h>
using namespace std;
int k;
const int MAX = 1e6 + 5;
int f[MAX], cnt[MAX];
string s;
long long ans;
int main()
{
cin >> k >> s;
f[0] = s[0] - '0';
cnt[f[0]]++;
for (int i = 1; i < s.size(); ++i)
{
f[i] = f[i - 1] + s[i] - '0';
cnt[f[i]]++;
}
if (k == 0)
{
int count = 0;
for (int i = 0; i < s.size(); ++i)
{
if (s[i] == '0')
count++;
else
{
ans += (long long)count * (count + 1) / 2;
count = 0;
}
}
ans += (long long)count * (count + 1) / 2;
cout << ans << endl;
}
else
{
for (int i = 0; i <= f[s.size() - 1]; ++i)
{
if (i >= k)
ans += (long long)cnt[i] * cnt[i - k];
}
ans+=cnt[k];
cout << ans << endl;
}
return 0;
}
7.出栈序列判断
代码
#include <bits/stdc++.h>
using namespace std;
int n, num, cnt = 1;
int s[100005];
int top = 0;
int main()
{
scanf("%d", &n);
for (int i = 1; i <= n; ++i)
{
scanf("%d", &num);
if (cnt <= n)
{
if (top == 0 || s[top] != num)
{
for (int i = cnt; i <= num; ++i)
{
printf("push %d\n", i);
s[++top] = i;
}
cnt = num + 1;
printf("pop\n");
top--;
}
else if (s[top] == num)
{
printf("pop\n");
top--;
}
}
else
{
printf("pop\n");
top--;
}
}
return 0;
}
8.序列维护
代码
#include <bits/stdc++.h>
using namespace std;
int m, x, y;
string s;
struct node
{
int num, next;
} nd[1001];
int len;
int main()
{
scanf("%d", &m);
bool first = true;
int f;
while (m--)
{
cin >> s;
if (s == "insert")
{
cin >> x >> y;
if (first)
{
nd[++len].num = y;
nd[len].next = 0;
f = len;
first = false;
}
else
{
if (x == 0)
{
nd[++len].num = y;
nd[len].next = f;
f = len;
}
else
{
int index = f;
x--;
while (x--)
index = nd[index].next;
nd[++len].num = y;
nd[len].next = nd[index].next;
nd[index].next = len;
}
}
}
else if (s == "query")
{
cin>>x;
int index=f;
x--;
while(x--)
index = nd[index].next;
cout<<nd[index].num<<endl;
}
else if (s == "delete")
{
cin>>x;
if(x==1)
f=nd[f].next;
else
{
int index=f;
x-=2;
while(x--)
index = nd[index].next;
nd[index].next=nd[nd[index].next].next;
}
}
}
return 0;
}
9.网格判断
代码
#include <bits/stdc++.h>
using namespace std;
int n;
string mp[25];
int main()
{
cin >> n;
for (int i = 1; i <= n; ++i)
cin >> mp[i];
int cntw = 0, cntb = 0, cnt = 0;
for (int i = 1; i <= n; ++i)
{
for (int j = 0; j < n; ++j)
{
if (mp[i][j] == 'W')
cntw++;
else
cntb++;
if (j == 0 || mp[i][j] == mp[i][j - 1])
cnt++;
else
cnt = 0;
if (cnt >= 3)
{
cout << 0 << endl;
return 0;
}
}
if (cntw != cntb)
{
cout << 0 << endl;
return 0;
}
cntw = 0, cntb = 0, cnt = 0;
}
for (int j = 0; j < n; ++j)
{
for (int i = 1; i <= n; ++i)
{
if (mp[i][j] == 'W')
cntw++;
else
cntb++;
if (i == 0 || mp[i][j] == mp[i - 1][j])
cnt++;
else
cnt = 0;
if (cnt >= 3)
{
cout << 0 << endl;
return 0;
}
}
if (cntw != cntb)
{
cout << 0 << endl;
return 0;
}
cntw = 0, cntb = 0, cnt = 0;
}
cout << 1 << endl;
return 0;
}
10.整齐的数组
代码
#include <bits/stdc++.h>
using namespace std;
int t, n, a, b;
int main()
{
scanf("%d", &t);
while (t--)
{
scanf("%d", &n);
scanf("%d %d", &a, &b);
int num = abs(b - a);
a = b;
n -= 2;
while (n--)
{
scanf("%d", &b);
if (b - a != 0)
num = __gcd(num, abs(b - a));
a = b;
}
if(num==0)
cout<<-1<<endl;
else
cout<<num<<endl;
}
return 0;
}