http://codeforces.com/contest/758
2017第一场。。。。才三道题,,,还wa了好多发。。。赛后补了DF
A题:
题意:
全部补成一个数,加多少个数
tip:
找最大值
#include <cstdio>
#include <iostream>
#include <cmath>
#include <cstring>
using namespace std;
int main(){
int n;
scanf("%d",&n);
int minn = 0,sum=0;
for(int i = 1 ; i <= n ; i++){
int a;
scanf("%d",&a);
minn = max(minn,a);
sum += a;
}
printf("%d\n",minn*n-sum);
}
B题:
题意:
4个灯泡按着顺序排列,其中有一些问号。。。保证每个灯泡都出现至少一次,
分别输出RBYG多少个是问号
tip:
可以看出%之后的值,每个数都对应同一个颜色的灯泡,那么就可以算出来
#include <cstdio>
#include <iostream>
#include <cmath>
#include <cstring>
using namespace std;
char s[110],mp[5];
int book[5],a[5];
int main(){
scanf("%s",s);
for(int i = 0 ; i < strlen(s);i++){
int k = i%4;
if(s[i]!='!') mp[k] = s[i];
else book[k]++;
}
for(int i = 0 ; i < 4;i++){
if(mp[i]=='R')
a[0] = book[i];
if(mp[i]=='B')
a[1] = book[i];
if(mp[i]=='Y')
a[2] = book[i];
if(mp[i]=='G')
a[3] = book[i];
}
for(int i = 0 ; i < 4 ;i++)
printf("%d%c",a[i],i==3?'\n':' ');
}
C题:
题意:
老师提问,次数最多,最少,和固定位置的人被提问了多少次。
tip:
就是各种问题,欸。。。第一排和最后一排比较特殊,然后可以发现先n*m个人提问之后,(n-1)*m*2是一个循环,每个循环,第一行和最后一行的人被提问一次,其他两次,在判断剩下的是在从下到上还是从上到下的过程,在判断能不能判断到固定位置,欸。。。wa了5次
#include <cstdio>
#include <iostream>
#include <cmath>
#include <cstring>
using namespace std;
long long k,ansmin,ansmax,ans;
int n,m,x,y,pos;//youshang 2 zuoxia 1
void sov(){
k-=m*n;
long long pci,pom;
pci = k/((n-1)*m*2);
pom = k%((n-1)*m*2);
// cout << "pom = "<<pom <<"pci = "<<pci <<endl;
if(pom <= (n-1)*m && pom != 0){//shang
ansmin = pci+1;
ansmax =(n==2)?ansmin+1: 2*pci+2;
if(x == n){
ans = pci+1;
return;
}
if(pom <= (n-1-x)*m +y-1){//meiyudao
if(x==1) ans = pci+1;
else ans = 2*pci+1;
}
else{
if(x==1) ans = pci+2;
// else if(pos == 2) ans = pci+2;
else ans = 2*pci+2;
}
}
if(pom == 0){
// cout << "pos = "<<pos<<endl;
ansmin = pci+1;
ansmax = (n==2)?ansmin:pci*2+1;
if(x==n||x==1) ans = pci+1;
else ans = 2*pci+1;
}
if(pom > (n-1) * m){ //xia
ansmin = pci+1;
ansmax = (n==2)?ansmin+1:2*pci+3;
pom -= (n-1)*m;
if(x == 1){
ans = pci+2;
return;
}
if(pom <= (x-2)*m+y-1){//mei
if(x==n) {
ans = pci+1;
}
else ans = 2*pci+2;
}
else{
if(x==n)
ans = pci+2;
else ans = 2*pci+3;
}
}
}
void init(){
scanf("%d%d%I64d%d%d",&n,&m,&k,&x,&y);
if(n == 1){
if(k%m!=0){
ansmax = k/m+1;
ansmin = ansmax-1;
ans = (k%m>=y)?ansmax:ansmin;
}
else{
ansmax = ansmin = ans=k/m;
}
return;
}
if(x == 1) pos = 2;
else if(x == n) pos = 1;
else pos = 0;
if(k < m*n){
ansmin = 0;
ansmax = 1;
if((x-1)*m+y > k) ans = 0;
else ans=1;
}
else if(k == m*n){
ansmin = ansmax = ans = 1;
}
else{
sov();
}
}
int main(){
init();
printf("%I64d %I64d %I64d\n",ansmax,ansmin,ans);
}
D题:
题意:
一个数(超过long long)可以表示为要求的进制数下,再转化为10进制。
tip:
可以知道,分成越少份越好,于是在小于n的那些就可以并到一起,贪心怎么证啊,我也不知道,反正被过掉了。。。dp的话更直观,dp【i】【j】表示前i个位置,分了j份最小值,后来发现第二维没什么用,不过我总这样
F题:
题意:
给你n l r,l到r之间找出n个数字,然后等比,问有多少
tip:
n给这么大,实际上,由于不能重复,那么25以上就没了,然后其他的,无非是上升或者下降,直接算上升,最后*2就好了,然后上升的时候有,a*p^(n-1)/q^(n-1),枚举q,根据q枚举a,首先a在l r之间,然后呢,每一位都是整数,那么a就是q^(n-1)次方的倍数了,p也靠枚举。。。gcd(p,q)等于1 ,结果l和r之间。
#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;
int n,l,r;
long long ans;
long long quickpow(int i,int n){
long long res = 1;
while(n > 0){
if(n&1) res *= i;
i *= i;
n>>=1;
}
return res;
}
long long gcd(long long a,long long b){
return b==0?a:gcd(b,a%b);
}
void sov(){
for(int i = 1 ; i<= r; i++){
long long t = quickpow(i,n-1);
if(t > r) break;
for(int k = t ; k <= r ;k += t){
if(k < l) continue;
for(int j = 1; j < i ; j++){
if(gcd(i,j)==1){
long long tmp = quickpow(j,n-1);
if(tmp > r ) break;
if(k/t*tmp >= l && k/t*tmp <= r){
ans++;
}
}
}
}
}
printf("%I64d\n",ans*2);
}
void init(){
scanf("%d%d%d",&n,&l,&r);
if(n == 1) printf("%I64d\n",(long long)r-l+1);
else if(n == 2) printf("%I64d\n",(long long)(r-l+1)*(r-l));
else if(n >= 25) printf("0\n");
else{
sov();
}
}
int main(){
init();
}