cf链接地址
The great dog detective Sherlock Bones is on the verge of a new discovery. But for this problem, he needs the help of his most trusted advisor -you- to help him fetch the answer to this case.
He is given a string of zeros and ones and length N.
Let F(x, y) equal to the number of ones in the string between indices x and y inclusively.
Your task is to help Sherlock Bones find the number of ways to choose indices (i, j, k) such that i < j < k, sj is equal to 1, and F(i, j) is equal to F(j, k).
input
The first line of input is T – the number of test cases.
The first line of each test case is an integer N (3 ≤ N ≤ 2 × 105).
The second line is a string of zeros and ones of length N.
output
For each test case, output a line containing a single integer- the number of ways to choose indices (i, j, k).
example:
3
5
01010
6
101001
7
1101011
2
3
7
Time limit —— 1500 ms
Memory limit —— 262144 kB
题意:
给你01串,你需要找出能够满足以下条件的区间( i , j , k)的个数
① i < j < k ,
② 下标 j 所代表的数字为1
③ 区间 [i , j] 中1的个数和区间 [j , k] 的1的个数相同
问:符合上述条件的(i , j , k)有几个?
刚开始做的时候真的一点没想到DP,看了好久只能看出暴力,2e5的数据暴力又必超时,后来看了好多题解,终于看出点头绪来,做法是真的妙。
分析:
从这些条件中我们可以看出一些性质: [i , k] 中1 的个数必定是奇数且至少是1
所以我们需要任意区间的1的个数
①用前缀和预处理字符串,用g[i]表示1~i之间1的个数
我们还需要知道该区间是奇是偶,开二维数组处理区间的奇偶在2e5的长度上显然不可取,所以我们需要一点折中操作,我们只处理 i~n 的奇偶区间数,然后最后处理时从后往前遍历,
②找出 i~n 的1的奇偶区间数
这里就要运用到DP了
dp[i][0]是 i~n 中1的个数为偶数的区间个数
dp[i][1]是 i~n 中1的个数为奇数的区间个数
ps:这里要好好想想,dp数组代表的是区间的个数
代码:
if(a[i]=='1')//当a[i]==1时,当前的奇数区间=之前的偶数区间+1,
{ // 当前的偶数区间=之前的奇数区间
dp[i][1]=dp[i+1][0]+1;
dp[i][0]=dp[i+1][1];
}
else//当a[i]==0时,当前的奇数区间=之前的奇数区间
{ // 当前的偶数区间=之前的偶数区间+1
dp[i][1]=dp[i+1][1];
dp[i][0]=dp[i+1][0]+1;
}
③对 i 进行枚举,只要 [i,k] 中1的个数为奇数个,那么就一定存在符合条件的区间
关于这个k的问题,我们其实在求dp数组时就已经解决了,dp数组记录了后面所有的奇偶区间,我们要先找到一个离 i 最近的 j1 ,a[j1]=1且j1!=i
当a[i]=1时,[i,j1] 中1的个数是偶数,所以我们要找到若干个奇数区间 [j1+1,k],而dp数组记录的就是奇偶区间的个数,也就是说我们要找的奇数区间的个数就是dp[j1+1][1],这里面包含了k的所有情况,我们知道k的范围是 (j1+1,n],我们要找的就是k在这范围内所有情况中奇数区间的个数
同理,当a[i]=0时,[i,j1] 中1的个数是奇数,我们要找的偶区间 [j1+1,k]的个数就是dp[j1+1][0]
所以,枚举所有 i 的情况,累加他们,即可得到最终答案
代码:
#include
#include
using namespace std;
const int N=2e5+10;
int dp[N][2];
int g[N];
int main()
{
int t;
cin>>t;
while(t--)
{
memset(g,0,sizeof(g));
memset(dp,0,sizeof(dp));
int n;
string a;
cin>>n>>a;
g[0]=a[0]-'0';
for(int i=1;i<n;i++)//g数组记录1的前缀和
{
g[i]=g[i-1]+a[i]-'0';
}
for(int i=n-1;i>=0;i--)
{
if(a[i]=='1')//当a[i]==1时,当前的奇数区间=之前的偶数区间+1,
{ // 当前的偶数区间=之前的奇数区间
dp[i][1]=dp[i+1][0]+1;
dp[i][0]=dp[i+1][1];
}
else//当a[i]==0时,当前的奇数区间=之前的奇数区间
{ // 当前的偶数区间=之前的偶数区间+1
dp[i][1]=dp[i+1][1];
dp[i][0]=dp[i+1][0]+1;
}
}
long long ans=0;
int flag=0;
int j1=n;
for(int i=n-1;i>=0;i--)
{
if(flag==0)//先找到第一个离i最近的j1
{
if(a[i]=='1')
{
flag=true;
j1=i;
}
}
else//找到j1后判断[i,j1]区间中1个数的奇偶
{
if((g[j1]-g[i]+a[i]-'0')%2==0)
{
ans+=dp[j1+1][1];//如果是偶数,那么就需要找到[j1+1,k]的奇数区间的个数
}
else
{
ans+=dp[j1+1][0];//如果是奇数,那么就需要找到[j1+1,k]的偶数区间的个数
}
if(a[i]=='1')
{
j1=i;//因为j1的属性是距离i最近的1的下标,所有要一直更新
}
}
}
cout<<ans<<endl;
}
}
总结:这题做的时候的步骤应该是 推出 [i,k] 中1的个数为奇数——枚举i和k发现行不通——结合第一步发现 j1和[j1+1,k]的性质——想到dp——推动态转移方程。
反正我当时卡在第二步就放弃看别的题了。。。
cf链接地址
A lion, a mouse, and a beaver are one of the best teams at Animal University, and they have qualified to the ACM Arabella 2017 contest!
They want to choose their team name, and after many suggestions, they have reduced their options to two names: “FunkyMonkeys” and “WeWillEatYou”.
They then created a poll on Facebook to help them with their final decision.
The results of the poll are now with Dr. Samer, and he will use the name with the highest votes to register the team. Can you help Dr. Samer to know which team name they will register with?
input
The first line of input is T – the number of test cases.
The first line of each test case contains two integers a, b (1 ≤ a, b ≤ 100) - the number of votes for “FunkyMonkeys” and “WeWillEatYou” respectively.
output
For each test case, output a single line containing “FunkyMonkeys” (without quotes), if that name received more points or tied with “WeWillEatYou”, otherwise output “WeWillEatYou”.
example:
2
15 20
70 70
WeWillEatYou
FunkyMonkeys
Time limit —— 1000 ms
Memory limit —— 262144 kB
题意:
真不敢相信cf上有这种题,意思是选队名,a是“FunkyMonkeys”这个队名的票数,b是“WeWillEatYou”队名的票数,输出多的那个
#include
using namespace std;
int main()
{
int a,b,t;
cin>>t;
while(t--)
{
cin>>a>>b;
if(a>=b) cout<<"FunkyMonkeys\n";
else cout<<"WeWillEatYou\n";
}
}
cf链接地址
There are N kangaroos going out to eat at an Indian restaurant. The ith kangaroo wants to eat exactly xi food. The kangaroos all want to order the same size of plates, but each one can order more than one plate for themselves if they need to. If the kangaroo orders more than he needs, he can simply hide the leftovers in his pouch.
At this Indian restaurant, the cost of the plate is the same as its size. Since Karl the Kangaroo is paying and is low on money, he wants to know what is the minimum cost to feed all N kangaroos and what is the largest possible size of the plates that satisfies this minimum cost?
input
The first line of input is T – the number of test cases.
The first line of each test case is an integer N (1 ≤ N ≤ 105).
The second line contains N space-separated integers xi (1 ≤ xi ≤ 109).
output
For each test case, output a line containing two space-separated integers – the minimum cost and the maximum plate size that corresponds to when the total cost is minimized.
example:
2
1
5
2
4 2
5 5
6 2
Time limit —— 1000 ms
Memory limit —— 262144 kB
题意:
有N个袋鼠,每个袋鼠想吃xi的食物,袋鼠们去饭店吃饭且都要一样大小的盘子,如果袋鼠要的食物比盘子大,那么可以多要几个盘子,每个盘子的成本和它的大小一样,你需要找到最小成本,以及在这个最小成本下盘子的最大尺寸
分析:
这道题题意有点模糊,它是让你优先找到最小的成本,然后再找到这个最小的成本中盘子的最大尺寸,最小成本很明确,就是 xi 的和 sum,设盘子尺寸为m,要保证每一个xi%m==0,这样才不会出现成本大于sum的情况
那么盘子尺寸m的身份就很明朗了,是所有 xi 的最大公约数
代码:
#include
#include
using namespace std;
long long gcd(long long a,long long b)
{
//这个gcd函数得自己写,__gcd函数不能处理longlong
if(b!=0) return gcd(b,a%b);
return a;
}
int main()
{
int t;
//输入输出要么写快读,要么scanf printf ,不然会TLE
scanf("%d",&t);
while(t--)
{
long long int n,m;
long long sum=0;//注意要开longlong
scanf("%lld",&n);
scanf("%lld",&m);//先令m=第一个数
sum=m;
for(int i=1;i<n;i++)
{
long long int x;
scanf("%d",&x);
sum+=x;
m=gcd(m,x);//更新m
}
printf("%lld %lld\n",sum,m);
// cout<
}
}
//顺带一提,我所有不用cin cout的代码都是因为vj上会卡输入用时
cf链接地址
In a magical forest, there exists N bamboos that don’t quite get cut down the way you would expect.
Originally, the height of the ith bamboo is equal to hi. In one move, you can push down a bamboo and decrease its height by one, but this move magically causes all the other bamboos to increase in height by one.
If you can do as many moves as you like, is it possible to make all the bamboos have the same height?
input
The first line of input is T – the number of test cases.
The first line of each test case contains an integer N (1 ≤ N ≤ 105) - the number of bamboos.
The second line contains N space-separated integers hi (1 ≤ hi ≤ 105) - the original heights of the bamboos.
output
For each test case, output on a single line "yes” (without quotes), if you can make all the bamboos have the same height, and “no” otherwise.
example:
2
3
2 4 2
2
1 2
yes
no
Time limit —— 1000 ms
Memory limit —— 262144 kB
题意:
有N个竹子,它们有各有各的高度,你可以使其中任意一个竹子的高度-1,但同时其他竹子全部+1,这种操作可以进行任意多次,问能否使所有竹子高度一致
分析:
假设只有两根竹子,每次操作肯定使较高的-1,同时较矮+1,每次操作会使他们高差-2,所以我们只有当这两个竹子都奇或都偶时才能同高,换做n个竹子也一样,所以可以得出:是否能同高==是否都是奇数或偶数
代码:
#include
using namespace std;
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n,m,flag,s=0;
scanf("%d",&n);
scanf("%d",&m);
if(m%2==0) flag=0;
else flag=1;
for(int i=1;i<n;i++)
{
int x;
scanf("%d",&x);
if(x%2!=flag) s=1;
}
if(s==1) printf("no\n");
else printf("yes\n");
}
}
cf链接地址
There are two seagulls playing a very peculiar game. First they line up N unit squares in a line, all originally colored white.
Let L be the length of the longest continuous sub-segment of white unit squares. Let P be any prime that satisfies the condition that P<[ L 2 \frac{L}{2} 2L] . The player can choose any P if it satisfies the conditions but if there is no value of P that does, then P is set to 1.
The current player then proceeds to choose any continuous sub-segment of white unit squares of length P and paint them black. The player who can’t make a move loses.
If both players play optimally and the first player starts, which player is going to win the game?
input
The first line of input is T – the number of test cases.
Each test case contains a line with a single integer N (1 ≤ N ≤ 107).
output
For each test case, output on a single line “first” (without quotes) if the first player would win the game, or “second” if the second would win.
example:
2
2
5
second
first
Time limit —— 1000 ms
Memory limit —— 262144 kB
题意:
有两位棋手分别是 first 和 second 有N个方块,最开始都是白色,设L是白色方块的最长连续子段,设P是一个素数且P<= L 2 \frac{L}{2} 2L(向上取整),如果没有符合条件的P那么P=1,然后棋手可以把长度为P的白色方块连续子段涂成黑色,直到某一方无法继续,不能继续的那一方输了,谁赢输出谁。
分析:
设先手的棋手是A,另一位是B。
A每次先取中间一段涂黑,使两边的白色方块数相等,然后B怎么涂A跟着在对称的那一边涂,这样B将其中一半涂满的时候A也同时涂满,那么B就无处可涂,B必输。
但是,n较小时胜负可能不一定,所以我们枚举一下,发现n=2时A必输,n=3时,A只能涂两个格子,所以A也必输,而当n>=4时,就可以用我们上面说的套路了
代码:
#include
using namespace std;
int main()
{
int t;
cin>>t;
while(t--)
{
int n;
cin>>n;
if(n==2||n==3)
{
cout<<"second\n";
}
else
{
cout<<"first\n";
}
}
}
cf链接
When the monkey professor leaves his class for a short time, all the monkeys go bananas. N monkeys are lined up sitting side by side on their chairs. They each have the same joke book. Before the professor returns, M jokes were heard.
Each of the M jokes are said in the order given and have the following properties:
xi - position of the monkey who said it.
li – index of the joke in the book.
ki – volume the monkey says that joke.
When the monkey at position xi says the joke li, all monkeys at a distance less than or equal to ki from that monkey (including the monkey who said the joke) will fall off their chairs in laughter if they have never heard the joke li before.
If the joke li has been heard anytime during the past before, and the monkey hears it again, then he will sit back up in his chair.
A monkey can fall off his chair more than once (every time he hears a new joke), and if he is already on the ground and hears a new joke, he will stay on the ground.
Can you figure out how many monkeys will be in their seats by the time the professor comes back?
input
The first line of input is T – the number of test cases.
The first line of each test case is N, M (1 ≤ N ≤ 105) (1 ≤ M ≤ 105) – the number of monkeys in the class, and the number of jokes said before the professor returns.
The next M lines contain the description of each joke: xi, li, ki (1 ≤ xi ≤ N) (1 ≤ li ≤ 105) (0 ≤ ki ≤ N).
output
For each test case, output on a line a single integer - the number of monkeys in their seats after all jokes have been said.
example:
1
10 7
3 11 0
3 11 2
5 12 1
8 13 2
7 11 2
10 12 1
9 12 0
3
Time limit——2000 ms
Memory limit——262144 kB
题意:
有n个猴子一排坐,编号是1~n,讲m次笑话,每次讲笑话会有三个属性,x,l,k,x是讲笑话猴子的编号,l是笑话编号,k是猴子讲笑话的声音,和x的距离小于等于k的猴子都能听见。
当猴子听到一个没听过的笑话就会从椅子上摔下来(包括讲笑话的猴子),如果听到一个听过的笑话会坐会椅子上,如果它已经在地上又听到没听过的笑话,那它还会在地上。
问讲完m次笑话后有几个猴子坐在椅子上
分析:
猴子是否坐在椅子上是由他最后听到的笑话决定的,每次处理需要处理一个区间,所以用的是线段树,但是我不会写,看了看网上大佬们代码,找到一个勉强看懂的代码,用到是差分的思想和优先队列维护笑话编号
大佬代码源地址
代码:
#include
#include
#include
#include
using namespace std;
const int N=1e5+10;
int cnt[N],inq[N],type[N];
//cnt数组是差分数组,记录左右区间
//inq数组是猴子状态,下标并不是代表猴子们的编号
//type代表是笑话编号
int h[N],e[N*2],ne[N*2],idx;
void add(int a,int b)//链式前向星
{
e[idx]=b;
ne[idx]=h[a];
h[a]=idx++;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n,m;
memset(h,-1,sizeof(h));
idx=0;
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
int l=max(a-c,1),r=min(a+c,n);//找到左右区间
type[i]=b;//对笑话进行编号
//左区间以正数录入前向星
//右区间以负数录入前向星
add(l,i);
add(r+1,-i);
}
/* for(int i=1;i<=n;i++)
{
cout<
priority_queue<int> q;
memset(cnt,0,sizeof cnt);
memset(inq,0,sizeof inq);
int ans=0;
//从头到尾遍历一遍
//i代表猴子的下标
for(int i=1;i<=n;i++)
{
for(int j=h[i];j!=-1;j=ne[j])
{
int x=e[j];//注意x并不是什么编号,而是普通的下标
//如果是左区间,令对应的笑话的cnt++,入队,更改状态
if(x>0)
{
cnt[type[x]]++;
inq[x]=1;
q.push(x);
}
else//如果是右区间,令对应笑话的cnt--,将状态改为椅子上
{
cnt[type[-x]]--;
inq[-x]=0;
}
}
// cout<
while(!q.empty()&&inq[q.top()]==0)
{
q.pop();
//如果堆顶的状态是坐在椅子上的,则删除
}
if(q.empty()||cnt[type[q.top()]]>1)
{
++ans;
//如果堆是空的或者堆顶的笑话出现次数>1,则令ans++
}
}
printf("%d\n",ans);
}
}
cf链接地址
Old Macdonald wants to build a new hen house for his hens. He buys a new rectangular area of size N by M. The night before he builds the hen house, snake Rana devises an evil plan to plant bombs in K distinct cells in the area to kill the hens and eat them for dinner later.
The morning of, Old Macdonald notices that each of the K cells, where snake Rana planted a bomb, have a marking on them. That won’t stop him though, all he must do is build the hen house in an area with no bombs.
Assume that rows are numbered from top to bottom, and columns are numbered from left to right. Old Macdonald now wants to know the number of ways he can choose sub-rectangles of top left coordinates (x1, y1) and bottom right coordinates (x2, y2) (x1 ≤ x2) (y1 ≤ y2) such that there are no bombs in the sub rectangle.
input
The first line of input is T – the number of test cases.
The first line of each test case is three integers N, M, and K (1 ≤ N, M ≤ 104) (1 ≤ K ≤ 20).
The next K lines each contains distinct pair of integers x, y (1 ≤ x ≤ N) (1 ≤ y ≤ M) - where (x, y) is the coordinate of the bomb.
output
For each test case, output a line containing a single integer - the number of sub-rectangles that don’t contain any bombs.
example:
3
2 2 1
2 2
6 6 2
5 2
2 5
10000 10000 1
1 1
5
257
2500499925000000
Time limit——4000 ms
Memory limit——262144 kB
题意:
给你一个nm的矩阵,其中有k个点有炸弹,问其他没炸弹的子矩阵有多少?
分析第一个样例,22的矩阵点(2,2)有炸弹,则其他子矩阵有3+2个,3个面积为1的矩阵,2个面积为2的矩阵,总共5个.
分析:
考点是容斥定理,数论这块我几乎一点不会,找了个大佬的代码甚至都看不懂,稍作修改改成了自己能看懂的样子
大佬原博地址
代码:
#include
using namespace std;
const long long maxn=1e4+5;
const long long minn=-1;
struct node
{
long long x,y;
};
node nd[30];
int main()
{
int t;
cin>>t;
while(t--)
{
for(int i=0;i<30;i++) nd[i]={0,0};
long long minx,miny,maxx,maxy;
long long n,m,k;
long long ans=0;
cin>>n>>m>>k;
for(int i=1;i<=k;i++)
{
cin>>nd[i].x>>nd[i].y;
}
ans=(n*(n+1)/2)*(m*(m+1)/2);
for(int i=1;i<(1<<k);i++)
{
//初始化
maxx=minn;
maxy=minn;
minx=maxn;
miny=maxn;
int t=i;
int cnt=0;
int num=0;
while(t)
{
num++;
if(t%2)
{
cnt++;
maxx=max(maxx,nd[num].x);
maxy=max(maxy,nd[num].y);
minx=min(minx,nd[num].x);
miny=min(miny,nd[num].y);
//此处注意不要用cnt做下标
//cnt是检测到一个炸弹就+1
//
}
t/=2;
}
if(cnt)
{
long long int z;
if(cnt%2) z=1;
else z=-1;
ans-=z*minx*miny*(n-maxx+1)*(m-maxy+1);
//容斥定理,有奇数炸弹的情况加,偶数炸弹的情况减
}
}
cout<<ans<<endl;
}
return 0;
}
cf链接地址
The gorillas have recently discovered that the image on the surface of the water is actually a reflection of themselves. So, the next thing for them to discover is mirrored strings.
A mirrored string is a palindrome string that will not change if you view it on a mirror.
Examples of mirrored strings are “MOM”, “IOI” or “HUH”. Therefore, mirrored strings must contain only mirrored letters {A, H, I, M, O, T, U, V, W, X, Y} and be a palindrome.
e.g. IWWI, MHHM are mirrored strings, while IWIW, TFC are not.
A palindrome is a string that is read the same forwards and backwards.
Can you tell if string S is a mirrored string?
input
The first line of input is T – the number of test cases.
Each test case contains a non-empty string S of maximum length 1000. The string contains only uppercase English letters.
output
For each test case, output “yes” (without quotes) if the string S is a mirrored string, otherwise output “no”.
example:
3
IOI
ARABELLA
RACECAR
yes
no
no
Time limit——1000 ms
Memory limit——262144 kB
题意:
给你一个字符串,判断字符串是否是回文且只由{A, H, I, M, O, T, U, V, W, X, Y}组成,是的话输出yes,不是no。
代码:
#include
using namespace std;
char c[]={'A', 'H', 'I', 'M', 'O', 'T', 'U', 'V', 'W', 'X', 'Y'};
int main()
{
int t;
cin>>t;
while(t--)
{
string a;
cin>>a;
int n=a.size(),flag=0;
for(int i=0,j=n-1;i<n;i++,j--)//先判断是否是回文
{
if(a[i]!=a[j])
{
flag=1;
}
}
if(flag==1)
{
cout<<"no\n";
continue;
}
for(int i=0;i<a.size();i++)//判断是否是要求字母
{
int f=1;
for(int j=0;j<11;j++)
{
if(a[i]==c[j])
{
f=0;
}
}
if(f==1)
{
flag=1;
break;
}
}
if(flag==1) cout<<"no\n";
else cout<<"yes\n";
}
}
cf链接地址
Note: this is a harder version of Mirrored string I.
The gorillas have recently discovered that the image on the surface of the water is actually a reflection of themselves. So, the next thing for them to discover is mirrored strings.
A mirrored string is a palindrome string that will not change if you view it on a mirror.
Examples of mirrored strings are “MOM”, “IOI” or “HUH”. Therefore, mirrored strings must contain only mirrored letters {A, H, I, M, O, T, U, V, W, X, Y} and be a palindrome.
e.g. IWWI, MHHM are mirrored strings, while IWIW, TFC are not.
A palindrome is a string that is read the same forwards and backwards.
Given a string S of length N, help the gorillas by printing the length of the longest mirrored substring that can be made from string S.
A substring is a (possibly empty) string of characters that is contained in another string S. e.g. “Hell” is a substring of “Hello”.
input
The first line of input is T – the number of test cases.
Each test case contains a non-empty string S of maximum length 1000. The string contains only uppercase English letters.
output
For each test case, output on a line a single integer - the length of the longest mirrored substring that can be made from string S.
example:
3
IOIKIOOI
ROQ
WOWMAN
4
1
3
Time limit——1000 ms
Memory limit——262144 kB
题意:
是上一题的较难版本,判断条件和上一题一样,只不过是找一个子串,输出这个子串的最大长度,题目给了字符串长度最大1000
分析:
长度1000可以写一个n^2的算法,也就是说可以直接暴力,那我们先扫一遍,标记所有符合题意的字母,然后再判断回文
#include
#include
using namespace std;
char c[]={'A', 'H', 'I', 'M', 'O', 'T', 'U', 'V', 'W', 'X', 'Y'};
const int N=1010;
bool st[N];
bool ss(string a,int x,int y)//ss函数是判断是否是回文
{
for(int i=x,j=y;i<=j;i++,j--)
{
if(a[i]!=a[j])
{
return false;
}
}
return true;
}
int main()
{
int t;
cin>>t;
while(t--)
{
string a;
cin>>a;
int n=a.size();
memset(st,false,sizeof(st));
//先将符合题意的字母标记,在暴力找区间是否是回文
for(int i=0;i<n;i++)//该循环是将符合的字母记录
{
for(int j=0;j<11;j++)
{
if(a[i]==c[j])
{
st[i]=true;
}
}
}
int ans=0;
for(int i=0;i<n;i++)
{
if(st[i])//如果是符合的字母,就开始暴力
{
int j=i;
while(st[j])//i是左区间,j是右区间
{
if(ss(a,i,j))//判断[i,j]是否是回文
{
ans=max(ans,j-i+1);
}
j++;
}
}
}
cout<<ans<<endl;
}
}
cf链接地址
Physics cat likes to draw shapes and figure out their area. He starts by drawing a circle. Then inside the circle, he draws the triangle X, Y, Z - where Y is the center point of the circle, and X and Z touch the circumference of the circle. Please note that points X and Y always have the same x-coordinate.
Given L (the distance between Points X and Y) and A (the angle XYZ in degrees); help physics cat find the shaded area between the right side of the triangle and the circumference of the circle. And when we say help, we mean do all the work for him.
input
The first line of input is T – the number of test cases.
The first line of each test case is integers L and A (1 ≤ L ≤ 1000) (1 ≤ A ≤ 180).
output
For each test case, output on a line the area of the shaded region rounded to 6 decimal places.
example:
3
1 90
2 180
10 30
0.285398
6.283185
1.179939
Time limit——1000 ms
Memory limit——262144 kB
题意:
园内有一个三角形,三角形中有两个点在园的边上,有一个点是园的圆心,给你园的半径和三角形圆心顶点的度数,问三角形和园的边之间的面积是多少?
分析:
很简单,因为给了度数,所以先算扇形面积,再算三角形面积,两者一减就行,这题应该是考cmath库中sincos等三角函数的用法,这些函数是以弧度制计算而非角度制,所以要把角度转换成弧度,公式:PI*x/180,(x是角度)
代码:
#include
#include
using namespace std;
const double PI=3.1415926;
int main()
{
double r,a,t;
cin>>t;
while(t--)
{
cin>>r>>a;
double s1=PI*r*r*(a/360.0);
double s2=r*r*sin(PI*a/180.0)/2.0;
printf("%.6lf\n",s1-s2);
}
}
cf链接地址
The owls have the following equation:
Y = a × x2 + b × x
With a, b, and N given, they decide to put into a set the integer values of Y that are less than or equal to N and that are outputted from the equation from any positive integer x.
With that set of numbers, they come up with the problem of finding the winning digit among them.
The winning digit is a digit from 0 to 9 that will get the maximum number of points. How are points for a digit calculated you may ask? Well, be a bit more patient, I’m going to tell you now.
For each number in the set, if the digit was the most repeated digit or tied with other digits as the most repeated digit in the ith number of set S, then it would get one point from that ith number.
Can you tell the owls what the winning digit is?
input
The first line of input is T – the number of test cases.
The first line of each test case is a, b, and N (1 ≤ a, b, N ≤ 105).
output
For each test case, print on a line the winning digit with the maximum number of points. If there is a tie, print the minimum digit among them. If the set is empty, print - 1.
example:
2
1 2 50
20 3 10
3
-1
Time limit——1000 ms
Memory limit——262144 kB
题意:
这题唯一的难点就是翻译,题意看明白了就是水题。
有一个一元二次方程:Y = a × x × x + b × x,然后给你a和b还有一个N,这个N是Y的最大值,Y<=N 的时候,找到 Y 中出现次数最大的 0~9 的数字,然后这给这个数字的分数+1(如果有多个出现次数一样大的,分数都+1),问分数最大的数字是谁?如果有多个分数最大的数字,输出最小的。
分析:
先找到 Y,然后统计 Y 中那个数字分数+1,然后再找分数最大的数,所以问题就成了找 Y ,a和b范围是 [1,1e5],所以 Y 必定为正数,N最大1e5,时间1s,所以直接暴力从1循环开始
代码:
#include
#include
using namespace std;
int s[15];
long long f(long long a,long long b,long long x)
{
return a*x*x+b*x;
}
long long maxx(long long a,long long b)
{
if(a>b) return a;
else return b;
}
int main()
{
int t;
cin>>t;
while(t--)
{
memset(s,0,sizeof(s));
long long a,b,n,flag=0,mxx=0;
cin>>a>>b>>n;
for(int i=1;;i++)
{
int k=f(a,b,i);
if(k>n)//方程式在x正半轴是一直递增的,所以遇到大于N的直接break
{
if(i==1) flag=1;//当第一个k都大于N时,说明符合输出-1的条件
break;
}
int st[10]={0},mx=0;
while(k)
{
st[k%10]++;
mx=maxx(st[k%10],mx);//找到k中出现的最多次数
k/=10;
}
for(int j=0;j<=9;j++)
{
if(st[j]==mx)//如果==最多的次数,分数+1
{
s[j]++;
}
}
}
int ans,res=-1;
for(int i=0;i<=9;i++)
{
if(res<s[i])
{
ans=i;
res=s[i];
}
}
if(flag==1)
{
cout<<-1<<endl;
continue;
}
cout<<ans<<endl;
}
}
cf链接地址
In the magical forest, you come upon N walls that you think is a great place to store water for your animal friends. The ith wall consists of ai blocks stacked on top of each other.
Your job is to answer queries of two types:
For queries of the first type, print the amount of water that could be stored between all the walls.
For queries of the second type, increase the number of blocks on the xth wall by v.
input
The first line of input is T – the number of test cases.
The first line of each test case is integers N and Q (1 ≤ N, Q ≤ 105).
The second line contains N space-separated integers ai (1 ≤ ai ≤ 105).
The next Q lines contain either ‘P’ – denoting a query of the first type, or ‘U’ followed by x and v – denoting a query of the second type (1 ≤ x ≤ N) (1 ≤ v ≤ 104).
output
For each test case and query of the first type, output on a line the amount of water that could be stored between the walls.
example:
1
6 3
2 1 4 2 1 3
P
U 1 2
P
4
6
Time limit——3000 ms
Memory limit——262144 kB
题意:
有n面墙,有m次操作,操作有两种
第一种,P:输出存水量
第二种,U:将第x面墙增高v米
分析:
这题看出来用线段树了,但是我不会,代码是找的别的大佬的
大佬的原博客地址
代码:
#include
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define x first
#define y second
using namespace std;
typedef long long LL;
const int MX = 1e5 + 5;
const int inf = 0x3f3f3f3f;
int lx[MX], rx[MX], lmax[MX << 2], rmax[MX << 2];
LL h[MX], sum[MX << 2], add[MX << 2];
void PushUP(int rt) {
sum[rt] = sum[rt << 1] + sum[rt << 1 | 1];
lmax[rt] = h[lmax[rt << 1]] >= h[lmax[rt << 1 | 1]] ? lmax[rt << 1] : lmax[rt << 1 | 1];
rmax[rt] = h[rmax[rt << 1]] > h[rmax[rt << 1 | 1]] ? rmax[rt << 1] : rmax[rt << 1 | 1];
}
void PushDown(int rt, int m) {
if (add[rt]) {
add[rt << 1] = add[rt];
add[rt << 1 | 1] = add[rt];
sum[rt << 1] = add[rt] * (m - (m >> 1));
sum[rt << 1 | 1] = add[rt] * (m >> 1);
add[rt] = 0;
}
}
void build(int l, int r, int rt) {
add[rt] = 0;
if (l == r) {
lmax[rt] = rmax[rt] = l;
sum[rt] = min(h[lx[l]], h[rx[l]]);
return;
}
int m = (l + r) >> 1;
build(lson); build(rson);
PushUP(rt);
}
void up_val(int p, int v, int l, int r, int rt) {
if (l == r) {
h[p] += v;
return;
}
PushDown(rt, r - l + 1);
int m = (l + r) >> 1;
if (p <= m) up_val(p, v, lson);
else up_val(p, v, rson);
PushUP(rt);
}
void update(int L, int R, int x, int l, int r, int rt) {
if (L <= l && R >= r) {
sum[rt] = (LL)x * (r - l + 1);
add[rt] = (LL)x;
return;
}
PushDown(rt, r - l + 1);
int m = (l + r) >> 1;
if (L <= m) update(L, R, x, lson);
if (R > m) update(L, R, x, rson);
PushUP(rt);
}
int flag = 0;
int findleft(int L, int R, int x, int l, int r, int rt) {
if (L > R) return -1;
if (l == r) return rmax[rt];
PushDown(rt, r - l + 1);
int m = (l + r) >> 1, ret = -1;
if (ret == -1 && R > m && h[rmax[rt << 1 | 1]] >= x) ret = findleft(L, R, x, rson);
if (ret == -1 && L <= m && h[rmax[rt << 1]] >= x) ret = findleft(L, R, x, lson);
PushUP(rt);
return ret;
}
int findright(int L, int R, int x, int l, int r, int rt) {
if (L > R) return -1;
if (l == r) return lmax[rt];
PushDown(rt, r - l + 1);
int m = (l + r) >> 1, ret = -1;
if (ret == -1 && L <= m && h[lmax[rt << 1]] >= x) ret = findright(L, R, x, lson);
if (ret == -1 && R > m && h[lmax[rt << 1 | 1]] >= x) ret = findright(L, R, x, rson);
PushUP(rt);
return ret;
}
int find_lmax(int L, int R, int l, int r, int rt) {
if (L <= l && R >= r) return lmax[rt];
PushDown(rt, r - l + 1);
int m = (l + r) >> 1, ret = 0, t;
if (R > m) {
t = find_lmax(L, R, rson);
if (h[ret] <= h[t]) ret = t;
}
if (L <= m) {
t = find_lmax(L, R, lson);
if (h[ret] <= h[t]) ret = t;
}
PushUP(rt);
return ret;
}
int find_rmax(int L, int R, int l, int r, int rt) {
if (L <= l && R >= r) return rmax[rt];
PushDown(rt, r - l + 1);
int m = (l + r) >> 1, ret = 0, t;
if (L <= m) {
t = find_rmax(L, R, lson);
if (h[ret] <= h[t]) ret = t;
}
if (R > m) {
t = find_rmax(L, R, rson);
if (h[ret] <= h[t]) ret = t;
}
PushUP(rt);
return ret;
}
int T, n, m;
void print(int l, int r, int rt) {
if (l == r) {
printf("[%I64d]%c", sum[rt], l == n ? '\n' : ' ');
return;
}
PushDown(rt, r - l + 1);
int m = (l + r) >> 1;
print(lson); print(rson);
PushUP(rt);
}
namespace IO {
const int MX = 1e8; //1e7占用内存11000kb
char buf[MX]; int c, sz;
void begin() {
c = 0;
sz = fread(buf, 1, MX, stdin);
}
inline bool read(int &t) {
while (c < sz && buf[c] != '-' && (buf[c] < '0' || buf[c] > '9')) c++;
if (c >= sz) return false;
bool flag = 0;
if (buf[c] == '-') flag = 1, c++;
for (t = 0; c < sz && '0' <= buf[c] && buf[c] <= '9'; c++) t = t * 10 + buf[c] - '0';
if (flag) t = -t;
return true;
}
inline bool read(char str[]) {
while (c < sz && (buf[c] == ' ' || buf[c] == '\n')) c++;
if (c >= sz) return false;
int i;
for (i = 0; c < sz && buf[c] != ' ' && buf[c] != '\n'; i++, c++) str[i] = buf[c];
str[i] = '\0';
return true;
}
}
int main() {
//freopen("in.txt", "r", stdin);
//freopen("out2.txt", "w+", stdout);
IO::begin();
IO::read(T);
while (T--) {
IO::read(n); IO::read(m);
LL tot = 0;
for (int i = 1, x; i <= n; i++) {
IO::read(x); h[i] = x; tot += h[i];
}
for (int i = 1, mx = 1; i <= n; i++) {
if (h[i] >= h[mx]) mx = i;
lx[i] = mx;
}
for (int i = n, mx = n; i >= 1; i--) {
if (h[i] >= h[mx]) mx = i;
rx[i] = mx;
}
build(1, n, 1);
char op[10];
for (int i = 1, x, v; i <= m; i++) {
IO::read(op);
if (op[0] == 'P') printf("%I64d\n", sum[1] - tot);
if (op[0] == 'U') {
IO::read(x); IO::read(v);
up_val(x, v, 1, n, 1); tot += v;
int l = findleft(1, x - 1, h[x], 1, n, 1);
int r = findright(x + 1, n, h[x], 1, n, 1);
if (l != -1 && r != -1) continue;
if (l != -1) {
update(l + 1, x, h[x], 1, n, 1);
} else {
if (x > 1) {
l = find_lmax(1, x - 1, 1, n, 1);
update(l, x - 1, h[l], 1, n, 1);
}
update(x, x, h[x], 1, n, 1);
}
if (r != -1) {
update(x, r - 1, h[x], 1, n, 1);
} else {
if (x < n) {
r = find_rmax(x + 1, n, 1, n, 1);
update(x + 1, r, h[r], 1, n, 1);
}
update(x, x, h[x], 1, n, 1);
}
}
}
}
return 0;
}
cf链接地址
Every year, an elephant qualifies to the Arab Collegiate Programming Competition. He graduated this year, but that’s irrelephant. What’s important is that the location of the competition might not have been the same every year. Therefore, after every trip, he always has leftover money in the currency of the country he visited.
Now he wants to see how much Jordanian Dinars he has after all those competitions. Can you help him convert the leftover money from all competitions to Jordanian Dinar, if that makes any cents?
input
The first line of input is T – the number of test cases.
The first line of each test case contains C and N (1 ≤ C, N ≤ 100000), the number of currency types and the number of competitions, respectively.
The next C lines each contain the name of the currency Ci of maximum length 10 in lowercase and/or uppercase letters, and the value Vi of that currency in Jordanian Dinar (0 < Vi ≤ 1000). The names are case-sensitive.
The next N lines each contains an amount left over from each competition (0 ≤ Ni ≤ 1000), and the name of the currency of that amount (it is guaranteed that the name was either given in the input or is “JD”).
output
For each test case, print on a single line the total amount of money he has in Jordanian Dinar(JD) rounded to 6 decimal digits.
example:
1
3 5
dollar 0.71
euro 0.76
turkish 0.17
5.1 dollar
6 dollar
7 turkish
3 euro
1.1 JD
12.451000
Time limit——6000 ms
Memory limit——262144 kB
题意:
给你n种货币的名称和其对应的价值,然后你在不同地方赚了不同的钱,问最后你总共赚多少
分析:
需要用到哈希表,这里我用的unorder_map,map查找效率太低,会超时,这题对输入用时卡的紧,加快读方便输入string类型,
代码:
#include
#include
using namespace std;
unordered_map<string,double> mp;
int main()
{
ios::sync_with_stdio(false);
int t;
cin>>t;
while(t--)
{
mp.clear();
int n,m;
string a;
double f,sum=0;
cin>>n>>m;
for(int i=0;i<n;i++)
{
cin>>a>>f;
mp[a]=f;
}
mp["JD"]=1.0;//题目中说了货币价值比较标准的货币名字叫JD,所以记得要让它的价值=1
while(m--)
{
cin>>f>>a;
sum+=f*mp[a];
}
printf("%.6lf\n",sum);
}
}