文章目录
前言
说实话,现在的新生是一个比一个强啊。
博主刚进大学的时候啥也不会,没有参加过任何竞赛或是项目,顶多就是把C语言自学了一些。
现在都大三了,啥也没有,打了一堆铁,拿了一堆铜奖,搞得跟少林十八铜人似的,自愧不如。
再看现在的新生,各种妖魔鬼怪。真是长江后浪推前浪,前浪死在沙滩上。
悲伤还是要再悲伤一阵子的,我们还是先来看题解吧。
A - Consecutive Sum Riddle (思维+水题)
比赛链接:https://codeforces.com/problemset/problem/1594/A
题目大意
给定一个整数 n n n(1<= n n n<=1018),求一个区间 [ l , r ] [l,r] [l,r],满足:
1 . − 10 10 1018 ≤ l < r ≤ ≤l<r≤ ≤l<r≤ 10 10 1018
2 . l + ( l + 1 ) + … + ( r − 1 ) + r = n l+(l+1)+…+(r−1)+r=n l+(l+1)+…+(r−1)+r=n
输出符合条件的 l , r l,r l,r。
思路
很简单的思维题。
如果n是一个奇数,我们可以把n分成 n 2 {n\over 2} 2n与 n 2 + 1 {n\over 2}+1 2n+1;
如果n是一个偶数,那我们就可以利用对称性,取 l = 1 − n , r = n l=1-n,r=n l=1−n,r=n。
进一步去想,其实偶数和奇数都可以用对称性取 l = 1 − n , r = n l=1-n,r=n l=1−n,r=n。
看来是我想多了 ̄□ ̄||。
AC代码
#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+100;
int a[maxn];
int main()
{
int t;
ios::sync_with_stdio(false);
cin>>t;
while(t--)
{
long long n;
cin >> n;
if(n&1) cout<<n/2<<" "<<n/2+1<<endl;
else cout<<(n-1)*-1<<" "<<n<<endl;
}
}
B - Special Numbers (数论+位运算)
比赛链接:https://codeforces.com/problemset/problem/1594/B
题目大意
我们定义:对于每一个数字来说都有一些对它来说比较特别的数字。
例如, 4 4 4的特别数字有: 1 1 1( 4 4 4 0 0 0),4( 4 4 4 1 1 1),5( 4 4 4 1 1 1+ 4 4 4 0 0 0),16( 4 4 4 2 2 2),17( 4 4 4 2 2 2+ 4 4 4 0 0 0),20( 4 4 4 2 2 2+ 4 4 4 1 1 1), . . . ... ...
现在给出整数 n n n,求 n n n的第 k k k个特别数字。
由于答案可能很大,答案需要对109+7取模。
思路
一个数论,但没有那么难,也是见到过很多次了。
我们分析一下例子中的数字:
我们可以发现:n的第k个特殊数字是根据k的二进制来求的。
根据得到的规律就可以很轻松的解决问题了。
AC代码
#include<bits/stdc++.h>
using namespace std;
const long long mod=1e9+7;
const int maxn=2e5+100;
//快速幂,没用上
long long quickpower(long long base,long long power)
{
long long result=1;
while(power){
if(power&1) result=(result*base)%mod;
power>>=1;
base=(base*base)%mod;
}
return result;
}
int main()
{
int t;
ios::sync_with_stdio(false);
cin>>t;
while(t--)
{
long long n,k;
cin>>n>>k;
vector<int> arr;
while(k){
arr.push_back(k%2);
k/=2;
}
long long ans=0;
long long m=1;
for(int i=0;i<arr.size();i++){
if(arr[i]) ans=(ans+m)%mod;
m=(m*n)%mod;
}
cout<<ans<<endl;
}
}
C - Make Them Equal (思维)
比赛链接:https://codeforces.com/problemset/problem/1594/C
题目大意
给一个字符串长度为 n n n的字符串 s s s与一个字符 c c c。
问你最少需要多少次操作可以把字符串中所有的字符都变成字符 c c c。
操作方法:
选择一个数字 x ( 1 < = x < = n ) x(1<=x<=n) x(1<=x<=n),把所有无法整除 x x x的下标i位置的字符 s [ i ] s[i] s[i]变成 c c c。
输出操作次数与每次操作的 x x x的值。
思路
1.首先考虑特殊情况:字符串s中所有的字符都是c,就不需要操作;
2.其次,先考虑1次操作能不能全部解决:
第一种可行方案:我们要找一个不能被其他数整除的下标,并且这个下标处的字符已经是c了。
这种下标存在于 [ n 2 + 1 , n ] [{n\over 2}+1,n] [2n+1,n]。
int pos=-1;
for(int i=n/2+1; i<=n; i++)
{
if(s[i-1]==a)
{
pos=i;
break;
}
}
if(pos!=-1) cout<<"1\n"<<pos<<endl;
第二种可行方案:模拟x所有可能的值,暴力跑出结果。
for(int i=2; i<=n; i++)
{
flag=true;
for(int j=i; j<=n; j+=i)
{
if(s[j-1]!=a)
{
flag=false;
break;
}
}
if(flag)
{
pos=i;
break;
}
}
if(pos!=-1) cout<<"1\n"<<pos<<endl;
3.最后,如果还是不存在那么我们就直接选择 x = n x=n x=n与 x = n − 1 x=n-1 x=n−1。
由于 1 − n 1-n 1−n中只有 n n n可以整除 n n n,除了 n n n位置上的字符其他的字符都会变成 c c c;紧接着又由于 1 − n 1-n 1−n中只有 n − 1 n-1 n−1可以整除 n − 1 n-1 n−1,此时再把 n n n位置上的字符改成 c c c。
AC代码
#include<bits/stdc++.h>
using namespace std;
const long long mod=1e9+7;
const int maxn=2e5+100;
int main()
{
int t;
ios::sync_with_stdio(false);
cin>>t;
while(t--)
{
int n;
char a;
string s;
cin>>n>>a;
cin>>s;
int flag=true;
for(int i=0; i<n; i++)
if(s[i]!=a)
{
flag=false;
break;
}
if(flag)
cout<<"0"<<endl;
else
{
int pos=-1;
for(int i=n/2+1; i<=n; i++)
{
if(s[i-1]==a)
{
pos=i;
break;
}
}
if(pos!=-1) cout<<"1\n"<<pos<<endl;
else
{
for(int i=2; i<=n; i++)
{
flag=true;
for(int j=i; j<=n; j+=i)
{
if(s[j-1]!=a)
{
flag=false;
break;
}
}
if(flag)
{
pos=i;
break;
}
}
if(pos!=-1) cout<<"1\n"<<pos<<endl;
else
{
cout<<"2\n"<<n<<" "<<n-1<<endl;
}
}
}
}
}
E1 - Rubik’s Cube Coloring (easy version) (思维+取模运算)
比赛链接:https://codeforces.com/problemset/problem/1594/E1
题目大意
你现在有一颗高度为k的满二叉树,树上有 2 k − 1 2^k-1 2k−1个结点。
现在你要为这颗树上的结点涂色,可以选择6种不同的颜色为树涂色,并且需要遵循一下规则:
- 白色结点不能和白色/黄色结点相邻
- 黄色结点不能和白色/黄色结点相邻
- 绿色结点不能和绿色/蓝色结点相邻
- 蓝色结点不能和绿色/蓝色结点相邻
- 红色结点不能和红色/橘色结点相邻
- 橘色结点不能和红色/橘色结点相邻
问,一共有多少种涂色的方式?
思路
一个简单的思维题。
简单来说就是我们给一个结点涂上任意一种颜色之后,它的两个相邻结点就会少两种颜色。
相邻:结点A与结点B之间有一条边。
那这样的话,一开始整棵树都没有颜色,所以根节点可以6选1。剩下的结点都只能选4种。
所以答案就是 6 ∗ 4 6*4 6∗4 2 k − 2 2^k-2 2k−2。
中间涉及到取模,对于 2 2 2 k k k 如果我们再使用快速幂去算会导致最后的答案缺失很多。
(测试点 k = = 60 k==60 k==60,可以自己比较一下两者的值)
这里可以使用位运算:
1<<n <==> 2^n
然后转成long long,保证了精度与答案的准确性。
AC代码
#include<bits/stdc++.h>
using namespace std;
const long long mod=1e9+7;
long long quickpower(long long base,long long power)
{
long long result=1;
while(power){
if(power&1) result=(result*base)%mod;
power>>=1;
base=(base*base)%mod;
}
return result;
}
int main()
{
long long n;
cin>>n;
long long power=(1LL<<n)-2;
//cout<<power<<endl;
cout<<(6*quickpower(4,power))%mod<<endl;
}
感谢阅读,希望能对你产生一点用处。
(人人视频上权游七八季下架了,呜呜呜)