版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/ShadowGhostH/article/details/80175510
题目大意:给出题号、时间、judge。计算最后的罚时。模拟可以过,学妹的代码,Orz
#include <bits/stdc++.h>
using namespace std;
const int maxn=3000;
int wa[maxn];
set<int>ac;
int cnt;
int ans;
void init()
{
for(int i=0; i<maxn; i++)
wa[i]=0;
ac.clear();
cnt=0;
ans=0;
}
int main()
{
int t;
cin>>t;
while(t--)
{
init();
int n,m;
cin>>n>>m;
for(int i=0; i<m; i++)
{
int t;
string s1,s2;
cin>>t>>s1>>s2;
if(s2=="AC")
{
if(ac.count(t)) continue;
else
{
int tmp=(s1[1]-'0')*60+(s1[3]-'0')*10+s1[4]-'0';
// cout<<'*'<<tmp<<endl;
cnt++;
ans+=wa[t]+tmp;
ac.insert(t);
}
}
else
{
wa[t]+=20;
}
}
cout<<cnt<<' '<<ans<<endl;
}
}
题目大意:求1~n的k次方的和,学弟的代码,直接预处理所有然后O(1)输出,Orz
#include <bits/stdc++.h>
using namespace std;
const long long md = 1e9 + 7;
long long ans[7][10010];
long long sm[7][10010];
void init(){
for(long long i = 0; i <= 5; i++){
for(long long j = 1; j <= 10000; j++){
if(i == 0){
ans[i][j] = 1;
}else{
ans[i][j] = ans[i - 1][j] * j % md;
}
}
}
for(long long i = 0; i <= 5; i++){
for(long long j = 1; j <= 10000; j++){
if(j == 1){
sm[i][j] = ans[i][j];
}else{
sm[i][j] = (sm[i][j - 1] + ans[i][j]) % md;
}
}
}
}
int main()
{
int t;
scanf("%d", &t);
init();
while(t--){
int n, k;
scanf("%d %d", &n, &k);
printf("%lld\n", sm[k][n]);
}
return 0;
}
题目大意:给出一个序列,去掉任意一个数,问这个序列的最大gcd。可以处理前缀gcd和后缀gcd,然后枚举去掉哪个数。学妹的代码,Orz
#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
int a[maxn];
int qgcd[maxn];
int hgcd[maxn];
int main()
{
int t;
cin>>t;
while(t--)
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
qgcd[1]=a[1];
for(int i=2;i<=n;i++)
{
qgcd[i]=(__gcd(qgcd[i-1],a[i]));
}
hgcd[n]=a[n];
for(int i=n-1;i>=1;i--)
{
hgcd[i]=(__gcd(hgcd[i+1],a[i]));
}
int ans=-1;
for(int i=1;i<=n;i++)
{
if(i==1)
{
ans=max(ans,hgcd[2]);
}
else if(i==n)
{
ans=max(ans,qgcd[n-1]);
}
else
{
ans=max(ans,__gcd(qgcd[i-1],hgcd[i+1]));
}
}
cout<<ans<<endl;
}
return 0;
}
题目大意:给n个节点和n-1个操作,对应2~n的节点的操作,1表示和前面所有点连一条边,2表示无操作。问能否选取图中的一个子图,使得所有点只被一条边覆盖。
思路:对于所有操作为2的节点,他只能和编号比他大的,操作为1的节点连一条边。那么我们就从后往前遍历,看是否存在一个连续区间,2的个数比1多,若有,则不可。然后判断一下如果点数为奇数的话,也是不可以的。
这次是自己的代码。
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+5;
int a[maxn];
int main()
{
int T;
scanf("%d", &T);
while(T--)
{
int n;
bool can = true;
scanf("%d",&n);
for(int i=0; i<n-1; i++)
scanf("%d", &a[i]);
int cnt = 0;
for(int i=n-2; i>=0; i--)
{
if(a[i] == 1) cnt++;
else if(a[i] == 2) cnt--;
if(cnt<0) {
can = false;
break;
}
}
if(n&1) can = false;
if(can) puts("Yes");
else puts("No");
}
return 0;
}
题目大意:有n个点,初始都是未标记的,每个点有自己的位置和把它标记的花费,转化之后,对于所有未标记的点,他们的花费是它距离左侧最近标记点的距离。问怎么标记使得整张图的花费最少。
思路:策略的话用dp考虑,先将所有点按照位置编号升序排序,然后考虑每个点标记与不标记情况下的花费。dp[0][i]为在i点不标记情况下前i个点的最小花费,dp[1][i]为在i点标记的情况下的最小花费。需要用前缀和预处理一下任意两点间全部为未标记点时的花费。
我自己的代码 -.-
#include<bits/stdc++.h>
#define LL long long
using namespace std;
const int maxn = 3e3+5;
struct Node{
int id;
int val;
bool operator < (const Node &b) const{
return id < b.id;
}
}a[maxn];
LL dp[2][maxn];
LL dist[maxn][maxn];
int main()
{
int n;
while(~scanf("%d", &n))
{
memset(dist, 0, sizeof dist);
for(int i=0; i<n; i++)
scanf("%d%d", &a[i].id, &a[i].val);
sort(a, a+n);
for(int i=0; i<n; i++){
int temp = 0;
for(int j=i+1; j<n; j++){
temp += a[j].id - a[j-1].id;
dist[i][j] = dist[i][j-1] + temp;
//printf("#%d %d %d\n", i, j, dist[i][j]);
}
}
dp[0][0] = a[0].val;
dp[1][0] = a[0].val;
for(int i=1; i<n; i++)
{
dp[0][i] = dp[1][0] + dist[0][i]; //[0][i]不在i建
dp[1][i] = dp[1][0] + dist[0][i-1] + a[i].val; //[0][i]为在i建
//printf("*****%lld %lld\n", dp[0][i], dp[1][i]);
for(int j=1; j<i; j++)
{
dp[0][i] = min(dp[0][i], dp[1][j]+dist[j][i]); //不在i建
//dp[1][i] = min(dp[1][i], min(dp[0][j], dp[1][j]) + a[i].val); //在i建
}
dp[1][i] = min(dp[0][i-1], dp[1][i-1]) + a[i].val;
//printf("%d: %lld %lld\n", i, dp[0][i], dp[1][i]);
}
printf("%lld\n", min(dp[0][n-1], dp[1][n-1]));
}
}
D和H留坑待补。。