时间统计
模拟题
#include <bits/stdc++.h>
using namespace std;
string str;
int main()
{
int n;
cin>>n;
while(n--)
{
int t[2];
for(int c=0; c<2; c++)
{
cin>>str;
int len=str.size();
int k=0;
while(str[k]!='d')
k++;
int x=0;
for(int i=0; i<k; i++)
{
x=x*10+str[i]-'0';
}
k+=3;
int h=0,m=0,s=0;
int i=k;
//for(int i=k;i<len;i++)
{
h=(str[i]-'0')*10+str[i+1]-'0';
m=(str[i+3]-'0')*10+str[i+4]-'0';
s=(str[i+6]-'0')*10+str[i+7]-'0';
}
int ans=((24*x+h)*60+m)*60+s;
//cout<<ans<<endl;
t[c]=ans;
}
cout<<t[1]-t[0]<<endl;
}
return 0;
}
String
用数组h存行的编号,用数组l存列的编号。
通过一个三重循环将正方形中的字符与字符串S进行比较,维护数组x和y。x[i]表示第i行的字符出现的次数,y[j]表示第j列的字符出现的次数。
然后遍历x和y找出最大行和最大列并将编号存入相应的数组中。
#include <bits/stdc++.h>
using namespace std;
char a[6][6]={'0','1','2','3','4','5',
'6','7','8','9','A','B',
'C','D','E','F','G','H',
'I','J','K','L','M','N',
'O','P','Q','R','S','T',
'U','V','W','X','Y','Z'};
int x[6],y[6];
vector<int> h,l;
int main()
{
int T;
cin>>T;
while(T--)
{
string s;
cin>>s;
memset(x,0,sizeof(x));
memset(y,0,sizeof(y));
h.clear();
l.clear();
int len=s.size();
for(int i=0;i<6;i++)
for(int j=0;j<6;j++)
{
char c=a[i][j];
int sum=0;
for(int k=0;k<len;k++)
{
if(c==s[k]) sum++;
}
x[i]+=sum;
y[j]+=sum;
}
int max_x=0,max_y=0;
for(int i=0;i<6;i++)
{
max_x=max(max_x,x[i]);
max_y=max(max_y,y[i]);
}
for(int i=0;i<6;i++)
{
if(x[i]==max_x) h.push_back(i);
if(y[i]==max_y) l.push_back(i);
}
for(int i=0;i<h.size();i++)
for(int j=0;j<l.size();j++)
{
cout<<a[h[i]][l[j]];
}
cout<<endl;
}
return 0;
}
Boom
注意到x和y都是整数,把区域分成一个一个的格子,设a[i][j]表示第i行第j列的格子被几个炸弹波及。对于每一个矩形区域,通过一个二重循环维护数组a。然后a中的最大值即为所求。
#include <bits/stdc++.h>
using namespace std;
const int maxn=110;
int a[maxn][maxn];
int main()
{
int T;
cin>>T;
while(T--)
{
memset(a,0,sizeof(a));
int n;
cin>>n;
while(n--)
{
int x1,y1,x2,y2;
cin>>x1>>y1>>x2>>y2;
for(int i=x1;i<x2;i++)
for(int j=y1;j<y2;j++)
a[i][j]++;
}
int ans=0;
for(int i=0;i<maxn;i++)
for(int j=0;j<maxn;j++)
ans=max(ans,a[i][j]);
cout<<ans<<endl;
}
return 0;
}
Fibonacci进制
模拟题
题干说可以转化为多个值,取最小的值。但可以观察规律只转化成最小的值。
从最低位向高位依此填数,当填到第i位不够时,从前i-1位选若干位,将其值置为0来弥补空缺。而从前i-1位选时,优先选最接近的值。
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
const int maxn=45;
map<int,int> m;
int a[maxn],cnt,f[maxn];
long long ans,p[65];
void solve(int x)
{
memset(a,0,sizeof(a));
int i=0;
while(true)
{
if(x==0) break;
if(x>=f[i])
{
x-=f[i];
a[i]=1;
i++;
}
else
{
a[i]=1;
x=f[i]-x;
while(x)
{
int pos=lower_bound(f,f+cnt,x)-f;
if(f[pos]!=x) pos--;
a[pos]=0;
x-=f[pos];
}
}
}
ans=0;
for(int j=0;j<=i;j++)
{
if(a[j]) ans+=p[j];
}
cout<<ans<<endl;
}
void init()
{
cnt=0;
f[0]=1;f[1]=2;
for(int i=2;i<maxn;i++)
{
f[i]=f[i-1]+f[i-2];
m[f[i]]=i;
cnt++;
if(f[i]>INF) break;
}
p[0]=1;
for(int i=1;i<65;i++)
p[i]=p[i-1]*2;
}
int main()
{
int T;
cin>>T;
init();
while(T--)
{
int x;
cin>>x;
solve(x);
}
return 0;
}
吃货
用结构体来存放美食的价格和美味度。
对结构体数组按照价格低优先、同等价格美味度低优先排序。然后二分求出t元能买的美食的区间上界pos,答案就是[0,pos]的最大美味度。每次都进行循环来查询太慢了,可以设dp[i]表示区间[0,i]的最大美味度,这样,预处理dp后就可以做到O(1)查询。
#include <bits/stdc++.h>
using namespace std;
const int maxn=3e4+100;
struct node
{
int d,c;
bool operator<(const node &o)const
{
return d<o.d || d==o.d&&c<o.c;
}
}a[maxn];
int b[maxn],dp[maxn];
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int n,m;
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++)
scanf("%d%d",&a[i].d,&a[i].c);
sort(a,a+n);
memset(dp,0,sizeof(dp));
dp[0]=a[0].c;
for(int i=0;i<n;i++)
{
b[i]=a[i].d;
if(i==0) continue;
dp[i]=max(dp[i-1],a[i].c);
}
while(m--)
{
int x;
scanf("%d",&x);
int pos=upper_bound(b,b+n,x)-b;
if(b[pos]!=x) pos--;
printf("%d\n",pos<0?0:dp[pos]);
}
}
return 0;
}
又见斐波那契
矩阵快速幂。
根据递推公式:F(i)=F(i-1)+F(i-2)+i^3+i^2+i+1,
我们可以确定答案矩阵为F(i)+F(i-1)+(i+1)^3+(i+1)^2+(i+1)+1.
根据这两个矩阵,可以确定矩阵A和幂的次数为n-1.
#include <bits/stdc++.h>
#define mod 1000000007
using namespace std;
struct matrix
{
long long m[6][6];
matrix()
{
memset(m,0,sizeof(m));
}
};
matrix mul_mod(matrix a,matrix b)
{
matrix c;
for(int i=0; i<6; i++)
for(int j=0; j<6; j++)
for(int k=0; k<6; k++)
c.m[i][j]=(c.m[i][j]+a.m[i][k]*b.m[k][j]%mod)%mod;
return c;
}
matrix pow_mod(matrix a,long long n)
{
matrix ans=a,x=a;
n--;
while(n>0)
{
if(n&1)
ans=mul_mod(ans,x);
n>>=1;
x=mul_mod(x,x);
}
return ans;
}
void solve(long long n)
{
matrix tmp,ans,A;
A.m[0][0]=1;
A.m[0][1]=1;
A.m[1][0]=1;
A.m[2][0]=1;
A.m[2][2]=1;
A.m[3][0]=1;
A.m[3][2]=3;
A.m[3][3]=1;
A.m[4][0]=1;
A.m[4][2]=3;
A.m[4][3]=2;
A.m[4][4]=1;
A.m[5][0]=1;
A.m[5][2]=1;
A.m[5][3]=1;
A.m[5][4]=1;
A.m[5][5]=1;
tmp.m[0][0]=1;
tmp.m[0][1]=0;
tmp.m[0][2]=8;
tmp.m[0][3]=4;
tmp.m[0][4]=2;
tmp.m[0][5]=1;
if(n==1)
printf("%lld\n",1);
else
{
A=pow_mod(A,n-1);
ans=mul_mod(tmp,A);
printf("%lld\n",ans.m[0][0]);
}
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
long long n;
scanf("%lld",&n);
solve(n);
}
return 0;
}
统计颜色
定义一个二元组数组col,col[i]表示颜色为i的球,col[i]里面存放的是颜色为i的球在桶中的区间范围。每次查询区间[l,r]的桶中不同颜色的球时,枚举所有颜色的球,当col[i]中的区间与[l,r]有重叠时,计数加一。因为球的颜色数不超过61,所有时间不会超限。
#include <bits/stdc++.h>
using namespace std;
typedef pair<int,int> pa;
vector<pa> col[62];
void solve(int l,int r)
{
int ans=0;
for(int i=0;i<=60;i++)
{
for(int j=0;j<col[i].size();j++)
{
int x=col[i][j].first,y=col[i][j].second;
if(x<=l&&r<=y || l<x&&r>=x || l<=y&&r>y)
{
ans++;
break;
}
}
}
printf("%d\n",ans);
}
int main()
{
int n,m;
while(~scanf("%d%d",&n,&m))
{
for(int i=0;i<62;i++) col[i].clear();
int op,l,r,c;
while(m--)
{
scanf("%d%d%d",&op,&l,&r);
if(op==1)
{
scanf("%d",&c);
col[c].push_back(pa(l,r));
}
else
{
solve(l,r);
}
}
}
return 0;
}