A:九进制转十进制
#include<iostreamod> //1
#include<cmath>
using namespace std;
int main()
{
int n=2022;
int count=0,num=0;
while(n)
{
num+=(n%10)*pow(9,count);
n/=10;
count++;
}
printf("%d\n",num);
return 0;
}
B:顺子日期
#include<iostream> //2
using namespace std;
int main()
{
cout<<14<<endl;
return 0;
}
C:刷题统计
#include<iostream> /3
using namespace std;
//sum为一周做题数,x为做了多少周,m为周几做
int main()
{
long long int a,b,n,x,m,num=0;
cin>>a>>b>>n;
long long int sum=5*a+2*b;
x=n/sum;
n-=sum*x;
m=n/a;
if(m>=5)
{
n-=5*a;
if(n>b)
num=7;
else
num=6;
}
else
{
if(n%a==0)
num=m;
else
num=m+1;
}
num+=7*x;
cout<<num<<endl;
return 0;
}
D:修建灌木
#include<iostream> //4
#include<algorithm>
using namespace std;
const int N=1e4+10;
int a[N];
int main()
{
int n;
cin>>n;
for(int i=1;i<=n-i+1;i++)
{
a[i]=2*(n-i);
a[n-i+1]=a[i];
}
for(int i=1;i<=n;i++)
{
cout<<a[i]<<endl;
}
return 0;
}
E:X进制减法
#include<iostream> //5
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
const int N=1e6+10;
long long int a[N],b[N]={0},c[N];
int main()
{
long long int n,ma,mb;
cin>>n;
cin>>ma;
for(int i=ma;i>=1;i--)
{
cin>>a[i];
}
cin>>mb;
for(int i=mb;i>=1;i--)
{
cin>>b[i];
}
for(int i=ma;i>=1;i--)
{
c[i]=max(a[i],b[i])+1;
if(c[i]<2)
{
c[i]=2;
}
}
long long int x=1,cha=0;
for(int i=1;i<=ma;i++)
{
cha+=((a[i]-b[i])*x)%1000000007;
x*=c[i];
x=x%1000000007;
}
cout<<cha%1000000007<<endl;
return 0;
}
F:统计子矩阵
#include<iostream>
#include<algorithm>
using namespace std;
const int N=666;
long long int a[N][N],b[N][N];
int main()
{
long long int n,m,k,num=0;
cin>>n>>m>>k;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
cin>>a[i][j];
b[i][j]=b[i-1][j]+a[i][j];
}
}
long long int l=1,sum=0;
for(int i=1;i<=n;i++)
{
for(int j=i;j<=n;j++)
{
l=1;
sum=0;
for(int r=1;r<=m;r++)
{
long long int r1=b[j][r]-b[i-1][r];
if(sum+r1<=k)
{
sum+=r1;
num+=r-l+1;
}
else
{
long long int l1=b[j][l]-b[i-1][l];
while(l!=r&&sum+r1>k)
{
sum-=l1;
l++;
l1=b[j][l]-b[i-1][l];
}
if(sum+r1<=k)
{
sum+=r1;
num+=r-l+1;
}
else
l++;
}
}
}
}
cout<<num<<endl;
return 0;
}
G:积木画
本题是一个dp问题,由于用二维dp比较麻烦,可以使用一维dp,将I型积木看成一个格子,L型积木为1.5个格子,所以L型积木必须要2个一组,由于I型积木有竖着摆和横着摆2种方式,所以要乘2;
所以递推公式为:x[i]=2*x[i-1]+x[i-3];
#include<iostream>
#include<algorithm>
using namespace std;
const int mod=1000000007;
const int N=1e7+10;
long long int x[N];
int main()
{
long long int n;
cin>>n;
x[1]=1;
x[2]=2;
x[3]=5;
for(int i=4;i<=n;i++)
{
x[i]=(2*x[i-1]%mod+x[i-3]%mod)%mod;
}
cout<<x[n]%mod<<endl;
return 0;
}
H:扫雷
#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
const int N = 5e4 + 10, M = 1e6 + 7, X = 1e9 + 1;
int n, m;
struct node {int x, y, r;}b[N];
typedef long long ll;
ll Hash[M]; bool vis[N];
int id[M], res;
ll get_hs(int x, int y) { return (ll)x * X + y; }
int find(int x, int y) {
ll hs = get_hs(x, y);
int key = (hs % M + M) % M;
while (Hash[key] != -1 && Hash[key] != hs) {
key++;
if (key == M) key = 0;
} return key;
}
bool check(int x1, int y1, int r, int x, int y) {
int d = (x1 - x) * (x1 - x) + (y1 - y) * (y1 - y);
return d <= r * r;
}
void bfs(int pos) {
queue<int> q;
q.push(pos);
vis[pos] = 1;
while (q.size()) {
int t = q.front();
q.pop();
int x = b[t].x, y = b[t].y, r = b[t].r;
for (int xx = x - r; xx <= x + r; xx++) {
for (int yy = y - r; yy <= y + r; yy++) {
int key = find(xx, yy);
if (id[key] && !vis[id[key]] && check(x, y, r, xx, yy)) {
int pos = id[key];
vis[pos] = 1;
q.push(pos);
}
}
}
}
}
int main() {
cin >> n >> m;
memset(Hash, -1, sizeof(Hash));
int x, y, r;
for (int i = 1; i <= n; i++) {
cin >> x >> y >> r;
b[i] = { x, y, r };
int key = find(x, y);
if (Hash[key] == -1) Hash[key] = get_hs(x, y);
if (!id[key] || b[id[key]].r < r) id[key] = i;
}
for (int i = 1; i <= m; i++) {
cin >> x >> y >> r;
for (int xx = x - r; xx <= x + r; xx++)
for (int yy = y - r; yy <= y + r; yy++) {
int key = find(xx, yy);
if (id[key] && !vis[id[key]] && check(x, y, r, xx, yy)) bfs(id[key]);
}
}
for (int i = 1; i <= n; i++) {
int key = find(b[i].x, b[i].y);
int pos = id[key];
if (pos && vis[pos]) res++;
}
cout << res;
return 0;
}
I:李白打酒加强版
状态设计:dp[i][j][k]的值表示遇到i家店,j朵花,酒壶中还剩k斗酒的可能情况数;
状态转移方程:dp[i][j][k]=dp[i-1][j][k/2](i>1&&k%2==0) + dp[i][j-1][k+1](j>1);
边界设计:除了dp[0][0][2]=1,其他元素全为0;
他一共遇到店n次,遇到花m次。已知最后一次遇到的是花, 他正好把酒喝光了;所以
最后一次肯定遇到的是花,那么最后的结果便是dp[N][M-1][1];
#include<iostream>
#include<cstring>
using namespace std;
const int mod=1000000007,N=110;
long long dp[N * 2][N][N]; /* 店,花,酒 */
void slove()
{
int n, m;
cin>>n>>m;
memset(dp, 0, sizeof dp);
dp[0][0][2] = 1;
for(int i=0;i<=n;i++)
for(int j=0;j<=m;j++)
for(int k=0;k<=m;k++)
{
if(i&&k%2==0)
dp[i][j][k]+=dp[i-1][j][k/2]; /* 遇到店 */
if (j)
dp[i][j][k]+=dp[i][j-1][k+1]; /* 遇到花 */
dp[i][j][k]%=mod;
}
cout<<dp[n][m-1][1]<<endl;
}
int main()
{
int t;
cin>>t;
while(t--)
{
slove();
}
return 0;
}
J:砍竹子
贪心,先将高的竹子砍了,可能这些竹子之后会和矮的竹子一起砍了。然后用a[i][j]记录第i棵树砍了j次后的高度,开始的砍树次数就是所有的树都一次一次地砍为 1 所需要的次数和,然后遍历如果发现有相邻的两棵树高度相同我们的砍树次数就可以减少1 。
#include<iostream>
#include<algorithm>
#include<cmath>
typedef long long int ll;
using namespace std;
const int N=2e5+10;
ll a[N][8],b[8];
int main()
{
ll num=0,n,x,t;
cin>>n;
for(int i=1;i<=n;i++)
{
t=0;
cin>>x;
while(x!=1)
{
b[++t]=x;
x=sqrt(x/2+1);
}
num+=t;
for(int j=1;t>0;j++,t--)
{
a[i][j]=b[t];
}
}
for(int i=1;i<=7;i++)
{
for(int j=2;j<=n;j++)
{
if(a[j][i]&&a[j][i]==a[j-1][i])
num--;
}
}
cout<<num<<endl;
return 0;
}