五一放假开学前的最后一场cf,上午的新大月赛感觉还可以,但愿晚上能找到点感觉
A. Aramic script
思路:这题一看就是个字符串处理的水题,思路很清晰,但确实不是那么容易上手写
先读取,然后扔进set排序去重,最后统计,说起了感觉贼容易,写起来海星
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <cstring>
#include <map>
#include <cmath>
#include <string>
#include <queue>
#include <stack>
#include <set>
using namespace std;
const int maxn = 1e5+10;
map<string,bool> in;
int main()
{
int n;
ios::sync_with_stdio(false);
cin >> n;
int num = 0;
in.clear();
while(n--)
{
string s;
cin >> s;
int len = s.size();
set<char> con;
for(int i=0;i<len;i++)
{
con.insert(s[i]);
}
string now;
set<char> :: iterator it;
for(it = con.begin();it!=con.end();it++)
{
now += (*it);
}
if(!in[now])
{
in[now] = true;
num++;
}
}
cout << num << endl;
return 0;
}
B. Mancala
思路:放置炮弹游戏,由于只有14个弹口,果断暴力,注意一下开个long long就没什么问题了
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <cstring>
#include <map>
#include <cmath>
#include <string>
#include <queue>
#include <stack>
using namespace std;
const int maxn = 1e5+10;
long long a[14];
long long aa[14];
int main()
{
long long score = 0LL;
for(int i=0;i<14;i++)
{
scanf("%I64d",&a[i]);
aa[i] = a[i];
if(a[i]%2LL==0LL)
{
score += a[i];
//cout << score << "*" << endl;
}
}
for(int i=0;i<14;i++)
{
for(int j=0;j<14;j++)
{
a[j] = aa[j];
}
long long nowscore = 0LL;
long long num = a[i];
a[i] = 0LL;
long long base = num/14LL;
num %= 14LL;
int pos = (i+1)%14;
while(num)
{
a[pos]++;
num--;
pos = (pos+1)%14;
}
for(int j=0;j<14;j++)
{
if((a[j]+base)%2LL==0LL)
{
nowscore += a[j] + base;
}
}
if(nowscore > score)
{
score = nowscore;
//cout << i << "*" << nowscore << endl;
}
/*if(i==9)
{
for(int j=0;j<14;j++)
{
cout << a[j] << "*";
}
}*/
}
printf("%I64d\n",score);
return 0;
}
C. Valhalla Siege
思路:这题又是一个模拟,最好的方法就是预处理前缀和,过程中处理累和,扔进去二分查找一下即可定位,定位得到最终结果
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <cstring>
#include <map>
#include <cmath>
#include <string>
#include <queue>
#include <stack>
using namespace std;
const int maxn = 2e5+10;
long long a[maxn],ata[maxn];
int main()
{
int n,q;
//freopen("in.txt","r",stdin);
//while(scanf("%d%d",&n,&q)!=EOF)
//{
scanf("%d%d",&n,&q);
scanf("%I64d",&a[0]);
ata[0] = a[0];
for(int i=1;i<n;i++)
{
scanf("%I64d",&a[i]);
ata[i] = ata[i-1] + a[i];
}
long long att = 0LL;
for(int i=0;i<q;i++)
{
long long k;
scanf("%I64d",&k);
att += k;
int pos = upper_bound(ata,ata+n,att) - ata;
//cout << pos << "*" <<att<< endl;
if(pos == n)
{
pos = 0;
att = 0LL;
}
printf("%d\n",n-pos);
// }
}
return 0;
}
D. Ghosts
思路:这题确实不好做,一开始盯着望了近半小时毫无思路一开始想的是二维坐标可以做成计算几何,然而猛然发现这是个包括时间轴的三维坐标,于是事情似乎就不那么好处理了
其实,不难发现,一直都没能用上初始点在同一直线上这个结论,在这种没办法进一步进展的情况下,不妨随便写写,也比干坐着盯着看要好,说不定就水落石出了呢
于是
Xi = Xi0 + Vxi * T;
Yi = Yi0 + Vyi * T;
Xj = Xj0 + Vxj * T;
Yj = Yj0 + Vyi * T;
Yi0 = a * Xi0 + b;
Yj0 = a * Xj0 + b;
Xi = Xj
=>
Xi0 + Vxi * T = Xj0 + Vxj * T;
=>
T = (Xj0 - Xi0) / (Vxi - Vxj);
Yi = Yj
=>
Yi0 + Vyi * T = Yj0 + Vyi * T;
=>
T = (Yj0 - Yi0) / (Vyi - Vyj);
=>
T = a * (Xj0 - Xi0) / (Vyi - Vyj);
=>
(Xj0 - Xi0) / (Vxi - Vxj) = a * (Xj0 - Xi0) / (Vyi - Vyj);
=>
a *(Vxi - Vxj) = (Vyi - Vyj);
=>
a * Vxi - Vyi = a * Vxj - Vyj;
好吧,每个点碰撞的集合居然只与a,vx,vy有关,发现的那一刻简直不敢相信
但兴奋之余不可大意,这一对计算牵扯到了除法,就必须单独处理特殊值,那就是vx不可相等,显然,由此可知vx想等的情况可以直接排除,因为当vx相等时,等式不可能成立,于是统计a*vx-vy的数量并减去相同vx的情况,再处理一下就好了
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <cstring>
#include <map>
#include <cmath>
#include <string>
#include <queue>
#include <stack>
using namespace std;
const int maxn = 1e5+10;
typedef long long ll;
map<ll,ll> col;
map<ll,map<ll,ll> > same;
int main()
{
ll n,a,b;
//freopen("in.txt","r",stdin);
ios::sync_with_stdio(false);
while(cin >> n >> a >> b)
{
col.clear();
same.clear();
while(n--)
{
ll x,vx,vy;
cin >> x >> vx >> vy;
ll temp = a * vx - vy;
col[temp] ++;
same[temp][vx]++;
}
map <ll,ll> :: iterator it,it2;
ll re = 0LL;
for(it = col.begin();it != col.end();it++)
{
ll num = it->second;
ll v = it->first;
re += num * (num - 1LL);
//cout << "*" << num << endl;
for(it2 = same[v].begin();it2!=same[v].end();it2++)
{
ll samenum = it2->second;
re -= samenum * (samenum - 1LL);
//cout << (it2->first) << "**" << samenum << endl;
}
}
cout << re << endl;
}
return 0;
}