THUPC 2024初赛 组队VP 2024.12.7
组队的思路不会写太清楚,这个只供日后队内需要进行查看
C.前缀和
题面:
小兰喜欢随机数,TA首先选定了一个实数 \(0 < p < 1\),然后生成了 \(n\) 个随机数 \(x_1, \ldots, x_n\),每个数是独立按照如下方式生成的:
- \(x_i\) 有 \(p\) 的概率是 1,有 \((1-p)p\) 的概率是 2,有 \((1-p)^2p\) 的概率是 3,以此类推。
生成完这些随机数之后,小艾对这个数列求了前缀和,得到了数列 \(y_1, \ldots, y_n\)。
给定 \(1 \leq l \leq r \leq n\),小兰想知道,期望有多少 \(y_i\) 落在 \([l, r]\) 内?
输入:
从标准输入读入数据。
一行输入四个数 \(n, p, l, r\)。保证 \(1 \leq l \leq r \leq n \leq 10^9\),\(p\) 的位数不超过 6。
输出:
输出到标准输出。
你需要保证答案的绝对或相对误差不超过 \(10^{-6}\)。
样例:
3 0.5 1 2
————————
1.000000
思路:队友写的
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
double a[1000050]={0};
double p;
int main(){
int n,l,r;
scanf("%d %lf %d %d",&n,&p,&l,&r);
printf("%.7lf",(r-l+1)*p*1.0);
return 0;
}
E.转化
题面:
小E有 \(n\) 种颜色的球,其中第 \(i\) 种有 \(a_i\) 个。有两类工具,第一类可以把一个指定颜色的球变成一个任意颜色的球;第二类可以把一个指定颜色的球变成两个这种颜色的球。一个变化之后的球也可以通过工具产生新的变化。关于第 \(i\) 种颜色的第一类工具有 \(b_i\) 个,第二类工具有 \(c_i\) 个。小E 想知道,如果每一个工具最多只能使用一次,那么对于每种颜色 \(i\),第 \(i\) 种颜色的球最后最多能有多少个。以及,小E 最后最多能有多少个球。
输入:
第一行包含一个正整数 \(n\)。
第二行包含 \(n\) 个整数,其中第 \(i\) 个表示 \(a_i\)。
第三行包含 \(n\) 个整数,其中第 \(i\) 个表示 \(b_i\)。
第四行包含 \(n\) 个整数,其中第 \(i\) 个表示 \(c_i\)。
输出:
第一行包含 \(n\) 个整数,其中第 \(i\) 个表示如果每个工具最多使用一次,那么小 E 最后第 \(i\) 种颜色的球最多有多少个。
第二行包含一个整数,表示如果每个工具最多使用一次,那么小 E 最后最多能有多少个球。
样例:
1:
2
1 2
1 2
1 0
————
4 3
4
思路:对于第一个输出分别可记录可转化的数量ans,需要一个球才能转化的数量cnt,然后对于每个球减去其贡献然后再考虑这两个贡献
对于第二个输出要求,统计有球且可转化的,需要一个球可以转化而且可以转化出去一个的,然后最后计算需要一个球但是不可以转化的,然后数学关系写出即可。
#include<iostream>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<math.h>
#include<time.h>
#include<random>
#include<stack>
#include<string>
//#include<bits/stdc++.h>
#include <unordered_map>
#define ll long long
#define lowbit(x) (x & -x)
#define endl "\n"// 交互题记得删除
using namespace std;
mt19937 rnd(time(0));
const ll mod =2;
//const ll p=rnd()%mod;
const ll maxn=5e5+15;
ll ksm(ll x, ll y)
{
ll ans = 1;
while (y)
{
if (y & 1)
{
ans = ans % mod * (x % mod) % mod;
}
x = x % mod * (x % mod) % mod;
y >>= 1;
}
return ans % mod % mod;
}
ll gcd(ll x, ll y)
{
if (y == 0)
return x;
else
return gcd(y, x % y);
}
void fio()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
}
struct s
{
ll x;
ll y;
ll z;
}p[360000];
ll d[360000];
ll ans=0;
ll cnt=0;
int main()
{
fio();
ll n;
cin>>n;
for(ll i=1;i<=n;i++)cin>>p[i].x;
for(ll i=1;i<=n;i++)cin>>p[i].y;
for(ll i=1;i<=n;i++)cin>>p[i].z;
ll pd=0;
for(ll i=1;i<=n;i++)
{
if(p[i].x>0&&p[i].y>0)
{
ans+=min(p[i].y,p[i].x+p[i].z);//可转换
}
else if(p[i].x==0&&p[i].y==0)continue;
else if(p[i].y>0&&p[i].x==0)
{
cnt=cnt-1+min(p[i].y,p[i].z+1);
}
}
//cout<<ans<<endl;
for(ll i=1;i<=n;i++)
{
if(p[i].x>0&&p[i].y>0)
{
if(ans>0)
cout<<ans-min(p[i].y,p[i].x+p[i].z)+p[i].x+p[i].z+cnt<<" ";
else cout<<p[i].x<<" ";
}
else if(p[i].x==0&&p[i].y>0)
{
if(ans>0)
{
if(p[i].y>=p[i].z+1)
cout<<ans+cnt<<" ";
else
cout<<ans+cnt+p[i].z+1-p[i].y<<" ";
}
else cout<<0<<" ";
}
else if(p[i].x==0&&p[i].y==0)
{
if(ans>0)
cout<<ans+cnt+p[i].z<<" ";
else
cout<<ans<<" ";
}
else if(p[i].x>0&&p[i].y==0)
{
if(ans>0)
cout<<ans+cnt+p[i].x+p[i].z<<" ";
else cout<<p[i].x+p[i].z<<" ";
}
}
cout<<endl;
ll cf=0;
ll cnt=0;
ll u=0;
priority_queue<ll>q;
for(ll i=1;i<=n;i++)
{
if(p[i].x>0)
{
cf+=p[i].x+p[i].z;
if(p[i].y>0)
{
cnt+=min(p[i].y,p[i].x+p[i].z);
}
}
}
for(ll i=1;i<=n;i++)
{
if(p[i].x==0&&p[i].z==0)
continue;
else if(p[i].x==0&&p[i].y>0)
{
if(cnt>0)
{
cf=cf-1+p[i].z+1;
cnt-=1;
cnt+=min(p[i].y,p[i].z+1);
}
}
else if(p[i].x==0&&p[i].y==0)
{
if(p[i].z==0)continue;
else q.push(p[i].z);
}
}
while(!q.empty())
{
if(cnt>0)
{
cnt--;
cf+=q.top();
}
q.pop();
}
cout<<cf<<endl;
}
K.三步棋
题面:
K 家里有一条不成文的规矩。如果家里只有 K 和 H 两个人,那么两个人会通过一种叫作“三步棋”的游戏来决定谁做饭。三步棋的规则与五子棋有一些相似之处。众所周知,五子棋是一种先连出五枚己方棋子者获胜的游戏。与五子棋相同的是,三步棋中双方也轮流在网格状的棋盘上摆放棋子,并根据是否连成指定的图案决定胜负。与五子棋不同的是:
- 三步棋不区分双方的棋子,即可以认为双方执同色棋子进行游戏;
- 在判定时,指定的图案不能旋转;
- 如果连成指定的图案时,棋盘上的棋子数量恰好为 $3$ 的倍数,则连成指定的图案的一方获胜,否则判定该方负(即对方获胜)。
例如,如果指定的图案为
.o oo
且当前盘面为
o..o. o.o.. oo... o.o.. o..o.
时,认为没有连成给定的折线形图案,其中 o 表示棋子,. 表示空格;但若接下来在第二行第二列放一枚棋子,则连成了给定的图案,对应的棋子使用 @ 表示:
o..o. o@o.. @@... o.o.. o..o.
此时盘面上恰有 $11$ 枚棋子,而 $11$ 不是 $3$ 的倍数,所以判定放这枚棋子的玩家,也即先手输掉本局。
在 K 家,为了节约时间,通常使用 $5\times 5$ 的初始为空的棋盘进行三步棋。同时,每次也只会随机选择一个由不超过 $4$ 枚棋子组成的四连通图案。显然三步棋不存在平局,所以 K 和 H 约定由输的一方负责做饭。K 想知道,如果自己和 H 都足够聪明,那么以选中的图案进行的三步棋游戏是否为先手必胜;因为如果她更容易赢,她就要偷偷地给自己的妹妹放水。
输入:从标准输入读入数据。
输入文件包含多组数据。
输入的第一行包含一个正整数 $T$,表示数据组数。保证 $1\le T\le 200$。
对于每组数据,输入包含 $5$ 行,每行包括一个长度为 $5$ 且仅含 . 及 o 的字符串,表示指定的图案。保证每组数据中 o 至少出现一次,且所有 o 组成一个大小不超过 $4$ 的四连通块。
输出到标准输出。
对于每组数据输出一行。如果输入的图案为先手必胜,则输出 Far,否则输出 Away。
3
.....
oo...
.....
.....
.....
.o...
.o...
.....
.....
.....
.....
.....
.....
.ooo.
.....
样例1输出:
Far
Far
Away
样例1解释:
该样例包含三组数据。
第一组数据输入的图案为 $1$ 行 $2$ 列的 oo。显然,无论先手将棋子放在棋盘上的哪个位置,后手都只有两种策略:
- 和先手的棋子连成
oo,此时棋盘上只有 $2$ 枚棋子,故后手立即输掉游戏; - 不和先手的棋子连成
oo,但是接下来轮到先手时,先手可以任意连成oo,此时棋盘上恰有 $3$ 枚棋子,故先手取胜。
无论是哪种策略,后手都无法取胜,故对于 oo 而言先手必胜。
第二组数据输入的图案为 $2$ 行 $1$ 列的图案,与 oo 同理,可知为先手必胜。
第三组数据输入的图案为 $1$ 行 $3$ 列的 ooo,可以证明为先手必败。
子任务:
保证 $1\le T\le 200$。对于每组数据,保证输入的 $5\times 5$ 的由 . 和 o 组成的字符矩阵中至少含有一个 o,且所有 o 组成一个大小不超过 $4$ 的四连通块。
思路:对于三,四可以先考虑不受边界影响的情况,然后根据图形形状去计算改变先后手的情况即可,最多9步即可得出博弈答案。
#include<iostream>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<math.h>
#include<time.h>
#include<random>
#include<stack>
#include<string>
//#include<bits/stdc++.h>
#include <unordered_map>
#define ll long long
#define lowbit(x) (x & -x)
#define endl "\n"// 交互题记得删除
using namespace std;
mt19937 rnd(time(0));
const ll mod =2;
const ll p=rnd()%mod;
const ll maxn=5e5+15;
ll ksm(ll x, ll y)
{
ll ans = 1;
while (y)
{
if (y & 1)
{
ans = ans % mod * (x % mod) % mod;
}
x = x % mod * (x % mod) % mod;
y >>= 1;
}
return ans % mod % mod;
}
ll gcd(ll x, ll y)
{
if (y == 0)
return x;
else
return gcd(y, x % y);
}
void fio()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
}
int main()
{
fio();
ll t;
cin>>t;
while(t--)
{
string f[500];
ll ans=0;
for(ll i=1;i<=5;i++)cin>>f[i],f[i]='0'+f[i];
ll pd=0;
for(ll i=1;i<=5;i++)
{
for(ll j=1;j<=5;j++)
{
ans+=(f[i][j]=='o');
if(i>=2&&j>=2)
{
if(f[i][j]=='o'&&f[i-1][j]=='o'&&f[i][j-1]=='o'&&f[i-1][j-1]=='o')
pd=1;
}
if(j>=4)
{
if(f[i][j]=='o'&&f[i][j-1]=='o'&&f[i][j-2]=='o'&&f[i][j-3]=='o')
pd=1;
}
if(i>=4)
{
if(f[i][j]=='o'&&f[i-1][j]=='o'&&f[i-2][j]=='o'&&f[i-3][j]=='o')
pd=1;
}
}
}
if(ans==1)
cout<<"Away"<<endl;
else if(ans==2)
cout<<"Far"<<endl;
else if(ans==3)
{
cout<<"Away"<<endl;
}
else if(ans==4)
{
if(pd==1)
cout<<"Away"<<endl;
else
cout<<"Far"<<endl;
}
}
}
M.你说得对,但是AIGC
题面:
你说得对,但是众所周知 AIGC 是当下计算机领域最热门的方向之一,算协的几名成员也对此很有兴趣,经过长时间的奋战,终于研发出了一款全新的语言大模型——ChatSAA。
你说得对,但是当模型即将发布之时,开发团队忽然发现模型存在重大问题——由于开发团队的某名成员沉迷于一款中文二字英文七字的游戏(见样例),导致训练模型时使用的语料库被莫名其妙地污染了,这使得模型生成的句子全都带有一个相同的前缀。
你说得对,但是紧急更换语料库重新训练显然已经来不及了,无奈开发团队只能在文档中注明:本模型的最大特性(而非bug)在于生成文本的前19个字符,这既是模型独特的防伪标记,也充分彰显了算协团队的人文情怀和文化素养。
你说得对,但是一个微不足道的问题在于:这会让人们一眼就能分辨出哪些句子是由 AI 生成的,这会对那些打算用 AI 来写作业的同学很不友好。
你说得对,但是现在你手里有一些句子,这些句子有的是由 ChatSAA 生成的,有的是人类写的(假设人类没有刻意模仿 ChatSAA 的生成特性),你需要写一个程序来辨别二者。
输入:
从标准输入读入数据。
你说得对,但是你的程序应当输入一行,一个字符串 $ s $ 表示需要判断的句子,满足 $ |s| \leq 200 $,且 $ s $ 由包括空格在内的 ASCII 可见字符(即 ASCII 码在 32~126 的字符)组成
输出:
输出到标准输出。
你说得对,但是你的程序应当输出一行,一个字符串表示判断结果,如果这句话是 AI 生成的,输出 AI,否则输出 Human。
样例:
You are right, but "Sao Lei (Winmine)" is a game whose Chinese name contains two characters while English name contains seven.
——————————
AI
,
Ni shuo de dui, dan shi zhe ju hua bu shi yi "You are right, but " kai tou de.
——————————
Human
,
You are wrong. Here is why. The English name of game "G****** I*****" contains 14 characters (including a space), not 7.
Human
思路:队友写的,检查前19个字符有没有“Yor are right,but”
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
string s="You are right, but ";
int main(){
string str="";
char x;
int jd=1;
while(scanf("%c",&x)!=EOF){
str+=x;
if(str.length()>=19){
jd=0;
for(int i=0;i<19;i++){
if(s[i]!=str[i]){
jd=1;
break;
}
}
}
}
if(jd){
printf("Human");
}else{
printf("AI");
}
return 0;
}

浙公网安备 33010602011771号