codeforces Round#747 div2
A
题意:
找到一对l到r使得l累加到r的和为n
题解
#include <bits/stdc++.h>
#define eb emplace_back
#define divUp(a,b) (a+b-1)/b
#define mkp(x,y) make_pair(x,y)
#define all(v) begin(v),end(v)
#define int long long
using namespace std;
typedef unsigned long long ull;
typedef pair<int, int> pii;
bool checkP2(int n) {return n > 0 and (n & (n - 1)) == 0;};
void solve() {
int n;
cin>>n;
cout<<-n+1<<' '<<n<<endl;
}
signed main() {
ios::sync_with_stdio(false);cin.tie(0);
int _; cin >> _; while (_--)
solve();
return 0;
}
B
题意:
一个数字要求只能是n的不同次方组成,求这些数字中第k大个
思路:
只能由不同的n的次方组成,也就意味着是一个二进制数,当n等于2时,k就是第k大个数,二进制可以表示任何数,所以其他的数字按照二进制模拟即可
题解:
#include <bits/stdc++.h>
#define eb emplace_back
#define divUp(a,b) (a+b-1)/b
#define mkp(x,y) make_pair(x,y)
#define all(v) begin(v),end(v)
#define int long long
using namespace std;
typedef unsigned long long ull;
typedef pair<int, int> pii;
bool checkP2(int n) {return n > 0 and (n & (n - 1)) == 0;};
const int mod=1e9+7;
void solve() {
int n,k;
cin>>n>>k;
if(n==2) {
cout<<k<<endl;
return;
}
int res=0;
int a=1;
while(k){
if(k&1) res=(res+a)%mod;
a=(a*n)%mod;
k>>=1;
}
cout<<res<<endl;
}
signed main() {
ios::sync_with_stdio(false);cin.tie(0);
int _; cin >> _; while (_--)
solve();
return 0;
}
C
题意:
给定一个字符串和一个字符c,选择一个x只有当下标i(从1开始)不能被x整除时,s[i]可以变成c,求最小操作次数
思路:
当字符串中全是c的时候操作就是0次,当字符串中由一个数x满足n/x=1,并且这个位置时c,则只需要一次,因为n/x=1表示1~n中只有一个x的倍数,就是x本身,其他情况都可以通过n和n-1两次操作转化
题解:
#include <bits/stdc++.h>
#define eb emplace_back
#define divUp(a,b) (a+b-1)/b
#define mkp(x,y) make_pair(x,y)
#define all(v) begin(v),end(v)
#define int long long
using namespace std;
typedef unsigned long long ull;
typedef pair<int, int> pii;
bool checkP2(int n) {return n > 0 and (n & (n - 1)) == 0;};
const int mod=1e9+7;
void solve() {
int n;
char c;
cin>>n>>c;
string s;
cin>>s;
bool ok=true;
int cnt=0;
for(auto i:s){
if(i!=c) ok=false,cnt++;
}
if(ok){
cout<<0<<endl;
return;
}
if(s[n-1]!=c and cnt==1){
cout<<1<<endl;
cout<<n-1<<endl;
return;
}
if(s[n-1]==c and cnt){
cout<<1<<endl;
cout<<n<<endl;
return;
}
for(int i=0;i<n;i++){
if(n/(i+1)<=1 and s[i]==c) {
cout<<1<<endl;
cout<<i+1<<endl;
return;
}
}
cout<<2<<endl;
cout<<n<<' '<<n-1<<endl;
}
signed main() {
ios::sync_with_stdio(false);cin.tie(0);
int _; cin >> _; while (_--)
solve();
return 0;
}
D
题意:
由n个玩家,m个回合,每个回合包括两次玩家u和v,和一个字符串,表示u说v时imposter或者crewmate,假如u时crewmate一定说的是真话,imposter一定说的是假话,求解最大可能的imposter数量或者判定这些话中有矛盾
思路:
判定有矛盾可以使用扩展域并查集来进行,比如u说v是imposter,这里先假设u是crewmate,那么表示v在说谎,把v的crewmate域和u的imposter域合并,把v的imposter域和u的crewmate合并,假如在未合并前发现,u的imposter域和v的imposter域有共同的根节点,则表明有矛盾,或者说最后看每个玩家的imposter域和crewmate域有没有连通,连通表示有矛盾,判断数量的话,可以使用维护每个域的size,然后找到根节点中imposter域和crewmate中最大的加上,因为可以判断他有没有矛盾,但不能说某个玩家一定是哪个域里的
题解:
#include <bits/stdc++.h>
#define eb emplace_back
#define divUp(a,b) (a+b-1)/b
#define mkp(x,y) make_pair(x,y)
#define all(v) begin(v),end(v)
#define int long long
using namespace std;
typedef unsigned long long ull;
typedef pair<int, int> pii;
bool checkP2(int n) {return n > 0 and (n & (n - 1)) == 0;};
const int N = 2000100;
int p[N * 3];
int s[N * 3];
int find(int x) {
if (x != p[x]) p[x] = find(p[x]);
return p[x];
}
void merge(int a, int b) {
int pa = find(a), pb = find(b);
if (pa != pb) {
p[pb] = pa;
s[pa] += s[pb];
}
}
int vis[N];
void solve() {
int n, m;
cin >> n >> m;
int u, v;
string str;
for (int i = 1; i <= 2 * n; i++) p[i] = i, s[i] = i <= n;//两个域只需要一个域赋值即可;
bool ok = true;
int tem = m;
while (m--) {
cin >> u >> v >> str;
int u_i = u, u_c = u + n;
int v_i = v, v_c = v + n;
if (str == "imposter") {
if (find(u_c) == find(v_c)) {
ok = false;
}
merge(u_c, v_i);
merge(u_i, v_c);
} else {
if (str == "crewmate") {
if (find(u_c) == find(v_i)) {
ok = false;
}
merge(u_c, v_c);
merge(u_i, v_i);
}
}
}
if (!ok) {
cout << -1 << endl;
return;
}
int mmax = 0;
for (int i = 1; i <= n; i++) {
if (p[i] == i) mmax += max(s[i], s[i + n]);
}
if (tem == 0) mmax = n;
cout << mmax << endl;
}
signed main() {
ios::sync_with_stdio(false); cin.tie(0);
int _; cin >> _; while (_--)
solve();
return 0;
}
E1
题意:
给定2k-1个节点,一共6种颜色,每个节点需要染色,并且遵循以下规则:
a white node can not be neighboring with white and yellow nodes;
a yellow node can not be neighboring with white and yellow nodes;
a green node can not be neighboring with green and blue nodes;
a blue node can not be neighboring with green and blue nodes;
a red node can not be neighboring with red and orange nodes;
an orange node can not be neighboring with red and orange nodes;
思路:
根节点有6种染色方法,字节点就是4种,当前子节点的一个子节点也是4种,样例就是6x4x4x4x4x4x4=24576,解法有很多种,这里写一个记忆化dfs
题解:
#include <bits/stdc++.h>
#define eb emplace_back
#define divUp(a,b) (a+b-1)/b
#define mkp(x,y) make_pair(x,y)
#define all(v) begin(v),end(v)
#define int long long
using namespace std;
typedef unsigned long long ull;
typedef pair<int, int> pii;
bool checkP2(int n) {return n > 0 and (n & (n - 1)) == 0;};
int f[100];
int res=6;
const int mod=1e9+7;
int dfs(int u){
if(u==1) return 4;
if(f[u]) return f[u]%mod;
f[u]=((dfs(u-1)%mod*dfs(u-1)%mod)%mod*4)%mod;
return f[u]%mod;
}
int qmi(int a,int b,int p){//快速幂
int res=1%p;
while(b){
if(b&1) res=res*a%p;
a=a*a%p;
b>>=1;
}
return res;
}
void solve() {
int k;
cin>>k;
int cur=dfs(k);
int mod2=qmi(2,mod-2,mod);
cout<<(cur*mod2%mod*3%mod)%mod<<endl;
}
signed main() {
ios::sync_with_stdio(false);cin.tie(0);
//int _; cin >> _; while (_--)
solve();
return 0;
}