2014年乌拉尔校赛,题很新,也是蛮有质量的,建议把题全做完。
部分题解from KILLBILL's source code~
A题:组合数求一下就可以了,注意k的值有坑。
#include<cstdio>
#include<cstring>
#include<algorithm>
#define mt(a,b) memset(a,b,sizeof(a))
using namespace std;
const int M=1e5+10;
char a[M];
int num[32];
int C[32][32];
int main(){
for(int i=0;i<32;i++){
C[i][i]=1;
C[i][0]=1;
}
for(int i=1;i<32;i++){
for(int j=1;j<i;j++){
C[i][j]=C[i-1][j]+C[i-1][j-1];
}
}
int k;
while(~scanf("%s%d",a,&k)){
mt(num,0);
for(int i=0;a[i];i++){
num[a[i]-'a']++;
}
sort(num,num+26);
int sum=0;
int kk=0;
for(int i=25;i>=0;i--){
sum+=num[i];
kk++;
if(kk==k) break;
}
printf("%d ",sum);
if(k==26){
puts("1");
continue;
}
if(num[26-k]==0){
puts("1");
continue;
}
if(num[26-k-1]!=num[26-k]){
puts("1");
continue;
}
int cn=0,cm=0;
for(int i=0;i<26;i++){
if(num[i]==num[26-k]){
cn++;
}
}
for(int i=26-k;i<26;i++){
if(num[i]==num[26-k]){
cm++;
}
}
printf("%d\n",C[cn][cm]);
}
return 0;
}
B题:水题,模拟一下。
#include<cstdio>
int main(){
int t,n,k,ans;
while(~scanf("%d",&t)){
while(t--){
scanf("%d%d",&n,&k);
int x=n/k;
int y=n%k;
ans=y*(x+1)*(n-x-1)+(k-y)*x*(n-x);
printf("%d\n",ans/2);
}
}
return 0;
}
C题:
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<string>
#include<queue>
#include<cmath>
#include<stack>
#include<set>
#include<map>
#define LL long long
#define INF 0x3f3f3f3f
#define CLR(a, b) memset(a, b, sizeof(a))
using namespace std;
char s[400000];
bool CanChange[400000];
int used[1000];
void output(){
for(int i=0;s[i];i++){
if(s[i] != '?')continue;
CanChange[i] = true;
if(i%2 == 0){
s[i] = 'z';
}else{
s[i] = 'a';
}
}
}
int main(){
int k;
while(scanf("%s",s)!=EOF){
scanf("%d",&k);
memset(CanChange,0,sizeof CanChange);
memset(used,0,sizeof used);
output();
for(int i=0; s[i]; i++){
used[s[i]]++;
}
int cnt = 0;
for(int i='a'; i<='z'; i++){
if(!used[i])continue;
cnt++;
}
if(cnt>=k){
puts(s);
continue;
}
bool ok = true;
k -= cnt;
while(k--){
int who,pos;
int dt = -INF;
for(int i='a'; i<='z' ;i++){
if(used[i])continue;
for(int j=0; s[j]; j++){
if(CanChange[j] == 0)continue;
char now = s[j];
if(used[now] == 1)continue;
int getbefore,getnow;
if(j%2 == 0){
getbefore = now;
getnow = i;
}else{
getbefore = -now;
getnow = -i;
}
if(getnow-getbefore>dt){
dt = getnow-getbefore;
who = i;
pos = j;
}
}
}
if(dt == -INF){
ok=false;
break;
}
used[s[pos]] --;
used[who] = 1;
s[pos] = who;
CanChange[pos] = false;
}
if(!ok){
puts("-1");
}else{
puts(s);
}
}
return 0;
}
D题:
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<string>
#include<queue>
#include<cmath>
#include<stack>
#include<set>
#include<map>
#define LL long long
#define INF 0x3f3f3f3f
#define CLR(a, b) memset(a, b, sizeof(a))
using namespace std;
const int maxn = 1000;
char mp[maxn][maxn];
int nextx[]={-1,0,1,0}; // shunshizheng up,right,down,left;
int nexty[]={0,1,0,-1};
int n,m;
bool isOver(int x,int y){
if(x<0||y<0||x>=n||y>=m){
return true;
}
return false;
}
int val[1000];
int number;
int nownum;
int num[1000000];
int getval(){
if(number == nownum){
return num[nownum-1];
}
return num[nownum++];
}
int main(){
while(scanf("%d%d",&n,&m)!=EOF){
for(int i=0;i<n;i++){
scanf("%s",mp[i]);
}
scanf("%d",&number);
for(int i=0;i<number;i++){
scanf("%d",&num[i]);
}
int stp = 0;
nownum = 0;
int x = 0,y = 0;
int nowdir = 1;
int nowval = 0;
memset(val,0,sizeof val);
while(1){
if(mp[x][y] == '^'){
nowdir = 0;
}else if(mp[x][y] == '>'){
nowdir = 1;
}else if(mp[x][y] == 'v'){
nowdir = 2;
}else if(mp[x][y] == '<'){
nowdir = 3;
}else if(mp[x][y] == '+'){
nowval++;
}else if(mp[x][y] == '-'){
nowval--;
}else if(mp[x][y] == '.'){
}else if(mp[x][y] == '?'){
nowval = getval();
}else if(mp[x][y] == '!'){
printf("%d\n",nowval);
nowval = 0;
}else if(mp[x][y] == '@'){
if(nowval == 0){
nowdir --;
if(nowdir == -1)nowdir = 3;
}else{
nowdir ++;
if(nowdir == 4)nowdir = 0;
}
}else if(mp[x][y]>='A' && mp[x][y]<='Z'){
swap(val[mp[x][y]],nowval);
}else if(mp[x][y] == '#'){
break;
}
if(abs(nowval)>100000){
puts("OVERFLOW ERROR");
break;
}
x = x+nextx[nowdir];
y = y+nexty[nowdir];
if(isOver(x,y)){
puts("RUNTIME ERROR");
break;
}
stp++;
if(stp >= 1000000){
puts("TIME LIMIT EXCEEDED");
break;
}
}
}
return 0;
}
E题:
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<string>
#include<queue>
#include<cmath>
#include<stack>
#include<set>
#include<map>
#define LL long long
#define INF 0x3f3f3f3f
#define CLR(a, b) memset(a, b, sizeof(a))
using namespace std;
char ch[110][110] =
{
"?.B?Av....A.AB<.",
".....>.?v>v..>.v",
".....>..>@...A..",
".....-...A>B-@..",
".....^A.+<...>^.",
"v........A.....<",
">C+CA--v........",
"^.....A@C!#....."
};
int main()
{
puts("8 16");
for(int i = 0; i < 8; i ++)
puts(ch[i]);
}
F题:汉诺塔的变形,知道汉诺塔的步数公式2^n-1,然后推一推就可以出来了。
#include<cstdio>
typedef long long LL;
const int M=55;
char a[M];
LL p[M];
int main(){
p[0]=1;
for(int i=1;i<M;i++){
p[i]=p[i-1]*2;
}
int n;
while(~scanf("%d%s",&n,a)){
LL ans=0;
int id=0;
for(int i=n;i>=1;i--){
int his=a[i-1]-'A';
if(his==id) continue;
ans+=p[i-1];
id=0^1^2^id^his;
}
printf("%lld\n",ans);
}
return 0;
}
G题:
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<string>
#include<queue>
#include<cmath>
#include<stack>
#include<set>
#include<map>
#define LL long long
#define INF 0x3f3f3f3f
#define CLR(a, b) memset(a, b, sizeof(a))
using namespace std;
const int MID = 330;
const int maxn = 100100;
const int MOD = 1000000007;
vector<int> G[maxn];
vector<int> up[maxn];
int add[maxn], val[maxn];
int query(int v)
{
int ret = val[v];
for(int i = 0; i < up[v].size(); i ++)
{
int u = up[v][i];
ret = (ret + add[u]) % MOD;
}
return ret;
}
void update(int v, int ad)
{
if(G[v].size() <= MID)
{
for(int i = 0; i < G[v].size(); i ++)
{
int u = G[v][i];
val[u] = (val[u] + ad) % MOD;
}
}
else
{
add[v] = (add[v] + ad) % MOD;
}
}
int main()
{
int n;
while(scanf("%d", &n) != EOF)
{
for(int i = 1; i <= n; i ++)
{
scanf("%d", &val[i]);
G[i].clear(), up[i].clear();
add[i] = 0;
}
for(int i = 1; i < n; i ++)
{
int u, v; scanf("%d%d", &u, &v);
G[u].push_back(v);
G[v].push_back(u);
}
for(int i = 1; i <= n; i ++)
{
for(int j = 0; j < G[i].size(); j ++)
{
int v = G[i][j];
if(G[v].size() > MID) up[i].push_back(v);
}
}
int m; scanf("%d", &m);
while(m --)
{
// puts("----------");
int op, v;
scanf("%d%d", &op, &v);
if(op == 1)
{
int ans = query(v);
update(v, ans);
}
else
{
int ans = query(v);
printf("%d\n", ans);
}
}
}
}
H题:看到图就能过了
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<string>
#include<queue>
#include<cmath>
#include<stack>
#include<set>
#include<map>
#define LL long long
#define INF 0x3f3f3f3f
#define CLR(a, b) memset(a, b, sizeof(a))
using namespace std;
int main()
{
char ans[10][10] = {"11", "01", "60", "80"};
int n;
while(scanf("%d", &n) != EOF)
{
if(n > 4) puts("Glupenky Pierre");
else
{
for(int i = 0; i < n; i ++)
{
printf("%s%c", ans[i], i == n - 1? '\n' : ' ');
}
}
}
}
I题:给a、b、c三条边,问能不能搞成三角形,且定点都是在整数格点上。
定一个顶点在原点,然后以两条边做圆,答案一定出现在圆上的整数格点上。
那么问题就转化为了在两个圆上分别找合法的点。
没有好方法,那就暴力找吧,当然,只要找1/4圆就可以了。
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<string>
#include<queue>
#include<cmath>
#include<stack>
#include<set>
#include<map>
#define LL long long
#define INF 0x3f3f3f3f
#define CLR(a, b) memset(a, b, sizeof(a))
using namespace std;
struct Point
{
int x, y;
Point(int x = 0, int y = 0)
:x(x), y(y){}
void out()
{
printf("%d %d\n", x, y);
}
};
vector<Point> v;
LL sqr(int x)
{
return 1ll * x * x;
}
LL dist(Point a, Point b)
{
return sqr(a.x - b.x) + sqr(a.y - b.y);
}
int main()
{
int a, b, c;
while(scanf("%d%d%d", &a, &b, &c) != EOF)
{
Point p1(0, 0);
v.clear();
for(int i = 0; i <= a; i ++)
{
LL l = 1ll * a * a - 1ll * i * i;
int q = sqrt(l + 0.0);
if(1ll * q * q != l) q ++;
if(1ll * q * q != l) continue;
v.push_back(Point(i, q));
}
for(int i = 0; i <= b; i ++)
{
LL l = 1ll * b * b - 1ll * i * i;
int q = sqrt(l + 0.0);
if(1ll * q * q != l) q ++;
if(1ll * q * q != l) continue;
Point tmp = Point(i, q);
for(int j = 0; j < v.size(); j ++)
{
LL l = dist(v[j], tmp);
if(l != 1ll * c * c) continue;
int q = sqrt(l + 0.0);
if(1ll * q * q != l) q ++;
if(1ll * q * q != l) continue;
p1.out();
tmp.out();
v[j].out();
return 0;
}
tmp = Point(-i, -q);
for(int j = 0; j < v.size(); j ++)
{
LL l = dist(v[j], tmp);
if(l != 1ll * c * c) continue;
int q = sqrt(l + 0.0);
if(1ll * q * q != l) q ++;
if(1ll * q * q != l) continue;
p1.out();
tmp.out();
v[j].out();
return 0;
}
tmp = Point(-i, q);
for(int j = 0; j < v.size(); j ++)
{
LL l = dist(v[j], tmp);
if(l != 1ll * c * c) continue;
int q = sqrt(l + 0.0);
if(1ll * q * q != l) q ++;
if(1ll * q * q != l) continue;
p1.out();
tmp.out();
v[j].out();
return 0;
}
tmp = Point(i, -q);
for(int j = 0; j < v.size(); j ++)
{
LL l = dist(v[j], tmp);
if(l != 1ll * c * c) continue;
// cout << l << " " << dist(v[j], tmp) << endl;
int q = sqrt(l + 0.0);
if(1ll * q * q != l) q ++;
if(1ll * q * q != l) continue;
p1.out();
tmp.out();
v[j].out();
return 0;
}
}
puts("-1");
}
}
J题:统计一下手机的型号就可以了
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<string>
#include<queue>
#include<cmath>
#include<stack>
#include<set>
#include<map>
#define LL long long
#define INF 0x3f3f3f3f
#define CLR(a, b) memset(a, b, sizeof(a))
using namespace std;
struct in{
string name;
int num,cost;
bool friend operator<(const in &a,const in &b){
if(a.num==b.num) return a.cost<b.cost;
return a.num>b.num;
}
}p[8];
int main(){
map<string,int> mp;
int e=0;
for(int i=0;i<6;i++){
string tmp;
cin>>tmp;
cin>>tmp;
int co;
scanf("%d",&co);
if(mp.find(tmp)==mp.end()){
mp[tmp]=e;
p[e].name=tmp;
p[e].num=0;
p[e].cost=0x3f3f3f3f;
e++;
}
int id=mp[tmp];
p[id].num++;
p[id].cost=min(p[id].cost,co);
}
sort(p,p+e);
cout<<p[0].name<<endl;
}
K题:图论,两遍BFS
#include<cstdio>
#include<cstring>
#include<queue>
#include<vector>
#define mt(a,b) memset(a,b,sizeof(a))
using namespace std;
const int M=1e5+10;
vector<int> g[M];
bool vis[M];
void bfs(int s,int d[]) {
mt(vis,0);
vis[s]=true;
queue<int> q;
while(!q.empty()) q.pop();
q.push(s);
while(!q.empty()) {
int u=q.front();
q.pop();
int len=g[u].size();
for(int i=0; i<len; i++) {
int v=g[u][i];
if(!vis[v]) {
vis[v]=true;
d[v]=d[u]+1;
q.push(v);
}
}
}
}
int sd[M],rd[M],d[M],ans;
struct Q {
int step,val,id;
} now,pre;
queue<Q> q;
void solve(int s,int f) {
ans=0;
mt(d,0);
now.step=0;
now.id=s;
now.val=rd[s];
while(!q.empty()) q.pop();
q.push(now);
while(!q.empty()) {
pre=q.front();
q.pop();
if(pre.id==f) {
ans=max(ans,pre.val);
continue;
}
int u=pre.id;
int len=g[u].size();
for(int i=0; i<len; i++) {
int v=g[u][i];
now.val=min(pre.val,rd[v]);
now.step=pre.step+1;
if(now.step==sd[v]&&d[v]<now.val) {
d[v]=now.val;
now.id=v;
q.push(now);
}
}
}
}
int main() {
int n,m,u,v,s,f,r;
while(~scanf("%d%d",&n,&m)) {
for(int i=1;i<=n;i++) g[i].clear();
while(m--) {
scanf("%d%d",&u,&v);
g[u].push_back(v);
g[v].push_back(u);
}
scanf("%d%d%d",&s,&f,&r);
bfs(s,sd);
bfs(r,rd);
solve(s,f);
printf("%d\n",ans);
}
return 0;
}
L题:分情况讨论:
(1)若x+y<C ,无解
(2)若x+y=C , 单一解,即X,Y
(3)若x+y>C,如果x<= C,a=x,b=C-x
否则,如果y<=C , a=C-y , b=y
否则a=0,b=C
当然这题是开放题,仁者见仁智者见智~
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#define LL __int64
#define mt(a,b) memset(a,b,sizeof(a))
using namespace std;
LL x,y,c;
int main() {
while(~scanf("%I64d%I64d%I64d",&x,&y,&c)) {
if(x+y==c) {
printf("%I64d %I64d\n",x,y);
continue;
}
if(x+y<c) {
puts("Impossible");
continue;
}
LL a,b;
if(x<=c){
a=x;
b=c-x;
}
else{
if(y<=c){
a=c-y;
b=y;
}
else{
a=0;
b=c;
}
}
printf("%I64d %I64d\n",a,b);
}
return 0;
}
/**
100000000 100000000 100000000
*/