闲话:很久没打周赛了(其实是没有),五个小时上线了三个小时,整体来说前面五题都很简单,不过在细节处一直没处理好,很考验心态。最后是a4题,第五题读完题就有事跑路了,不过也是道暴力枚举题,稍微二进制压缩一下而已。
大致意思是要去买三本书(一开始读成n本书),给出了价格,可以根据需要组合起来去付款,这里有个优惠,就是满500减100。
既然题目说满500减100,那么久尽量去凑多组500以上的,我们可以先排序,然后从小到大组一组记录价格总和,当和大于等于500时就可以将它们分成一组。因为这里只有三本书,所以很简单就算枚举也能过,这里的方法应该是使用于n的。
using namespace std;
const int N=1e5;
int a[N];
int main()
{
//IOS
int d;
int cnt=0;
while(cin>>d){
a[cnt++]=d;
}
sort(a,a+cnt);
ll ans=0;
int i=0;
ll t=0;
for(;i<cnt&&a[i]<500;i++){
t+=a[i];
if(t>=500){
ans+=(t-100);t=0;
}
}
if(t>0){
ans+=t;
}
for(;i<cnt;i++)ans+=(a[i]-100);
cout<<ans<<'\n';
return 0;
}
题目要求数三角形。原本有一个大三角形,现在在由往下切n条线,再平行于地面切k条线,问此时能包含的不同三角形有多少个。一共t组样例。
首先容易发现,三角形一个顶点是确定的,平行切了k刀,那么数的时候就要遍历底边,所以这里是k+1条底边,而每一边的情况是相同的,也就是说数出其中一种然后乘上k+1。
对于每组边,切n刀分成了n+1个小三角形,相邻若干个小三角形可以组成一个大点的三角形,所以从三角形大小入手,应该有n+1,n,n-1,~~,一直加到n-p=0,也就是最大的那个三角形,即n+1个组成的。很显然就是等差数列1加到n+1。答案再乘上上面说的k+1即可。
这里wa很很多遍,因为注意到答案要mod1e7,而我在计算等差数列时把/2放在了最后去计算,这完全是画蛇添足。因为等差数列结果(容易发现一定是奇数乘以偶数)取了模,所以它的奇偶性改变了,之后再去/2,那么就会有误差了,应该老老实实/2再去取模的。
using namespace std;
const int N=1e5;
const ll mod=1000000007;
int a[N];
int main()
{
//IOS
int t;cin>>t;
while(t--)
{
ll n,k;
cin>>k>>n;
ll ans=(((k+1)*(k+2)/2)%mod*(n+1))%mod;
cout<<ans<<'\n';
}
return 0;
}
给你一个只含 1 ~ 9 的 字符串s,字符串的长度小于10。你可以在任意两个字母之间插入“+”使得其成为一个合法的算式,可以一个“+”号都不插入,问你所有合法 算式 的总和.
字符串很短,暴力枚举每个地方加不加加号即可。枚举时可以二进制压缩一下。
using namespace std;
const int N=122;
const ll mod=1000000007;
ll dp[12][12];
int main()
{
//IOS
string s;cin>>s;
int len=s.length();
ll ans=0;
ll now=0;
for(int i=0;i<(1<<len-1);i++){
now=0;
for(int j=0;j<len;j++){
now=now*10+s[j]-'0';
if(j==len-1||(1<<j)&i){
ans+=now;
now=0;
}
}
}
cout<<ans<<'\n';
return 0;
}
要求翻译字符串,并且给出一个最大长度,超过了这个长度就是不合法的。
至于字符串格式,就是数字加字母表示该字母有多少个,只有小写字母并且一个时可以省去数字。
没什么好说的,模拟即可。
using namespace std;
const int N=1e5;
const ll mod=1000000007;
int a[N];
int main()
{
//IOS
int t;cin>>t;
while(t--){
string s;cin>>s;
int maxn;cin>>maxn;
string ans;
int len=s.length();
int p=1;
bool yes=1;
ll all=0;
for(int i=0;i<len;){
if(s[i]>='a'&&s[i]<='z'){
ans+=s[i];
all++;
i++;
}
else {
int j=i;
string temp;
temp+=s[j++];
while(s[j]>='0'&&s[j]<='9')temp+=s[j],j++;
ll o=atoi(temp.c_str());
all+=o;
if(all>maxn){
yes=0;break;}
while(o--)ans+=s[j];
i=j+1;
}
if(yes==0)break;
}
if(all>maxn||(s[len-1]>='0'&&s[len-1]<='9'))yes=0;
if(yes==0)cout<<"unfeasible\n";
else if(yes==1)cout<<ans<<'\n';
}
return 0;
}
给出一个“子串”和“父串”的规则,即“子串”为“父串”无限循环后的子串。现给n个串,求出不同的“父串数量”。
在判断归属关系时可以把父串拼接两边。先让答案对于n(视为每个串都是不相干的),遍历每个串,它与后面的串去比较,找到一个可以当它父串的,就让答案减1(这个串不是父传所以减掉),结束匹配(因为找到了就足够了)。
using namespace std;
const int N=122;
const ll mod=1000000007;
pair<string,string>all[N];
int yes[N];
int main()
{
//IOS
int n;cin>>n;
for(int i=1;i<=n;i++){
string t;cin>>t;
string tt;tt=t+t+t;
all[i]=make_pair(t,tt);
}
ll ans=n;
for(int i=1;i<=n;i++){
for(int j=i+1;j<=n;j++){
if(all[j].first.length()==all[i].first.length()&&all[j].second.find(all[i].first)!=string::npos){
ans--;
break;
}
}
}
cout<<ans<<'\n';
return 0;
}
三组ABC各有一定人数,选出共k个人,C一定要选c个人,AB都得选至少一人。求选择方案数。结果对1e7取模。
题目转为从C个人中选c个,A,B中选K-c个人,A,B至少选一个人的方案数。考虑直接组合数计算,然后减去A选K-c和B选K-c的方案数。(去掉A或B选不到一个人的情况)
注意先判断一下合理性。(选完c剩不到两个人)
这题难在组合数,因为结果要取模,如果按照有除法的方法可能存在除以0的情况。所以要换一种。
求组合数的方法有很多种,可以看这里。
因为有多组所以先预处理一下。
using namespace std;
const int N=2e5+2;
const ll mod=1000000007;
ll jie[N];
ll tow[N];
ll power(ll a,ll b,ll p) //return a^b mod p
{
ll temp = 1;
while(b)
{
if(b & 0x01)
{
temp = (temp * (a%p)) % p;
}
a = ( (a%p) * (a%p) ) % p;
b >>= 1;
}
return temp%p;
}
void init()
{
jie[0]=1;
for(int i=1;i<N;i++)jie[i]=jie[i-1]*i%mod;
tow[N-1]=power(jie[N-1],mod-2,mod);
for(int i=N-2;i>=0;i--) tow[i]=tow[i+1]*(i+1)%mod;
}
ll cal(ll n,ll m)
{
if(m>n) return 0;
return jie[n]*tow[m]%mod*tow[n-m]%mod;
}
int main()
{
//IOS
init();
int t;cin>>t;
while(t--){
ll A,B,C,k,c;
ll ans=0;
cin>>A>>B>>C>>k>>c;
if(k-c<2){
cout<<0<<'\n';continue;}
ll p=k-c;
ll o=cal(A,p)+cal(B,p);o%=mod;
ans=cal(A+B,p)-o+mod;
ans%=mod;
ans*=cal(C,c);
ans%=mod;
cout<<ans<<'\n';
}
return 0;
}
下面的题没读,都是有点难度的题(也有裸题),没读就不写了。