本次总结,心得和代码放在一起
E J
没AC
A
一个模拟题。处理好初始化,就任意他怎么输入。
B
一个比较神奇的题目,我记得我当时WA了一页。
他们的关系像一条链。
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
const int N = 2e5+10 ;
const LL mod = 2000120420010122 ;
char str[N] ;
LL a[4] ;
int main()
{
while(~scanf("%s" , str))
{
memset(a , 0 ,sizeof a) ;
for(int i = 0 ; str[i] ; i++)
{
if(str[i] == 'c' || str[i] == 'C') a[0] = (a[0] + 1 ) % mod ;
if(str[i] == 'w' || str[i] == 'W') a[1] = (a[0] + a[1] ) % mod ;
if(str[i] == 'b' || str[i] == 'B') a[2] = (a[1] + a[2] ) % mod ;
if(str[i] == 'c' || str[i] == 'C') a[3] = (a[2] + a[3] ) % mod ;
}
cout << a[3] << endl;
}
return 0 ;
}
C
每一个数字能被分割的次数是唯一的,不管你如何分割,分割的次序是如何的。
也就是说,这是一个伪博弈论。
你可以通过对区间$[l,r]$计算每一个数字的操作次数,进行判断。
如果区间的总操作次数奇数,那就是先手胜利。如果总操作数是偶数,那么后手胜利。
如果给定的k是1,那么不分胜负。
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
#define int long long
const int N = 1e5+10 ;
int l ,r , k ;
int op[N] ;
void init()
{
for(int i = 1 ; i < N ; i ++)
{
op[i] = 1 + op[i/k] * k ;
}
for(int i = 1 ; i <= r ; i ++) op[i] += op[i-1] ;
}
signed main()
{
while(cin >> l >> r >> k)
{
if(k == 1)
{
printf("Draw\n") ;
continue ;
}
init() ;
if((op[r]-op[l-1]) & 1 )
{
printf("XHRlyb\n") ;
}else
{
printf("Cwbc\n") ;
}
}
return 0 ;
}
D
我自己的代码过了80%的数据,然后看了人家的答案。思路大致相同,就是代码写法有点不一样。人家的过了,我的妹有。
思路
别看他是一连串的模,我们耐心的把它们分类讨论,就会发现针对每一个x,x%(r)%(r-1)%…%(l)的结果其实呈现一种周期函数。我们的代码在周期函数上进行累计求和即可,思想类似于前缀和。
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
#define int long long
int a , b , l ,r ;
int sum(int x)
{
return x * (x + 1) >> 1 ;
}
int prefix(int x)
{
return x/r * sum(l) + sum(min(x%r , l) ) ;
}
signed main()
{
while(~scanf("%lld%lld%lld%lld" ,&a,&b,&l,&r))
{
l -- ;
r -- ;
printf("%lld\n" , prefix(b) - prefix(a)) ;
}
return 0 ;
}
E
不会呢,暂时放一放哈
F
是一个水题哈,耐心分类讨论就可以啦。
注意就是两条线段的交集,有可能存在,也可能不存在。
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
#define int long long
int a , b , c , d ;
int gcd(int a ,int b)
{
return b ? gcd( b , a % b) : a ;
}
signed main()
{
while(cin >> a >> b >> c >> d )
{
int t = max(0ll, min(b, d) - max(a, c) + 1);
int sum = (d - c + 1) * (b - a + 1);
if(!t) printf("0/1\n");
else
{
int d = gcd(t , sum) ;
cout << t / d << "/" << sum / d << endl; ;
}
}
return 0 ;
}
G
这个题目比较简单。两次AC。
思路
先把s和和他相接的给标记了。
在这个的基础上,我们从叶子和叶子的直接父亲开始标记。这样一对一对的。然后叶子爷爷和叶子太爷这样一对一对标记。以此类推。每标记一对res++ .
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 5e5+10 , M = 2*N ;
int h[N], e[M], ne[M], idx;
int n , s ;
int res ;
bool st[N] ;
void add(int a, int b) // 添加一条边a->b
{
e[idx] = b, ne[idx] = h[a], h[a] = idx ++ ;
}
void dfs(int u , int fa)
{
for(int i = h[u] ; ~i ; i = ne[i])
{
int j= e[i] ;
if(j==fa) continue ;
dfs(j , u) ;
}
if(!st[u])
{
st[u] = 1 ;
st[fa] = 1 ;
res ++ ;
return ;
}
}
int main()
{
memset(h, -1, sizeof h);
scanf("%d%d", &n ,&s);
for(int i = 0 ; i < n - 1 ; i ++ )
{
int a , b ;
scanf("%d%d", &a , &b);
add(a, b);
add(b, a);
}
st[s] = 1 ;
for(int i = h[s] ; ~i ; i =ne[i])
{
int j = e[i] ;
if(j == s) continue ;
st[j] = 1 ;
}
res++ ;
dfs(s,-1) ;
cout << res << endl;
return 0 ;
}
H
这道题你如果能知道元年的干支是多少那就太爽了。但是没必要。题目给出了你2018年的干支,但是劝你不要拿这个进行推导,涉及负数,非常麻烦。
设年号N,N自己就在10和12之间分别做余数。
int off1 = n % 10 ;
int off2 = n % 12 ;
if(off1 > 3)
{
off1 -= 3 ;
}else
{
off1 += 7 ;
}
if(off2 > 3)
{
off2 -= 3 ;
}else
{
off2 += 9 ;
}
至于之间的加加减减,以及涉及的常量,都是推出来的。没有道理可言。
I
双关键字排序。
虽然思路直接但还是有坑的。
在进行double计算的时候,千万记得,先乘再除.你不用怕double乘了会越界,没必要操那份心。你需要担心的是,你如果先除了,会有误差,再乘,误差会放大。导致WA。切记。
#include <iostream>
#include <cstring>
#include <algorithm>
#include<string>
using namespace std;
#define fi first
#define se second
typedef pair<double, string> PII;
const int N = 2e5+10;
string name[N] ;
double noip[N] , oi1[N] , oi2[N] , oi3[N] , oi4[N] ;
int n ;
PII pcs[N] ;
int main()
{
while(~scanf("%d" , &n) )
{
double max_noip = -1 ;
double max_oi_1 = -1 ;
double max_oi_2 = -1 ;
double max_oi_3 = -1 ;
double max_oi_4 = -1 ;
for(int i = 0 ; i < n ; i++)
{
cin >> name[i] ;
// scanf("%lf",&noip[i]);
cin >> noip[i] ;
max_noip = max(max_noip , noip[i] ) ;
// scanf("%lf", &oi1[i]);
cin >> oi1[i] ;
max_oi_1 = max(max_oi_1 , oi1[i] ) ;
// scanf("%lf", &oi2[i]);
cin >> oi2[i] ;
max_oi_2 = max(max_oi_2 , oi2[i] ) ;
// scanf("%lf", &oi3[i]);
cin >> oi3[i] ;
max_oi_3 = max(max_oi_3 , oi3[i] ) ;
// scanf("%lf", &oi4[i]);
cin >> oi4[i] ;
max_oi_4 = max(max_oi_4 , oi4[i] ) ;
}
for(int i = 0 ; i < n ; i++ )
{
double all = (noip[i]* 150 / max_noip ) ;
all += (oi1[i] * 75.0 / max_oi_1 );
all += (oi2[i] * 75.0/ max_oi_2 ) ;
all += (oi3[i] * 150.0/ max_oi_3 ) ;
all += (oi4[i] * 150.0 / max_oi_4 ) ;
pcs[i] = {-all , name[i]} ;
}
sort(pcs , pcs + n) ;
for(int i = 0 ; i < n ; i++)
{
cout << pcs[i].se << " " ;
printf("%.5lf\n" , -pcs[i].fi) ;
}
}
return 0 ;
}
J
过了30%的数据。虽然看起来很简单,但其实坑多得是。看了人家的代码,要不就是极长,要不就是极其抽象。先撂着。