Codeforces Round #788 (Div. 2)
题意:对应c放入a,b其中之一(a,b,c均在1~n内)
- 环路定理的运用
- 并查集
- 快速幂
思路:
- 对a [ i ] 和 b [ i ]建边,可得到任意数量个环
- 自环 和 环上有确定的点,环内只有一种可能
- 环上没有确定的点,有两种可能
- 所以只用找环满足条件 3 的数量,输出对2的幂次mod1e9
#include<bits/stdc++.h>
#define debug0(x) cout << endl << "debug0: " << x << endl
#define fr(t, i, n) for (int i = t; i < n; i++)
using namespace std;
typedef long long LL;
typedef pair<int,int> PII;
const int N = 1e5+10,mod = 1e9+7;
int p[N];
int find(int u){
if(p[u] != u){
p[u] = find(p[u]);
}
return p[u];
}
LL qmi(LL a,int b,int p)
{
LL res=1;
while(b)//对b进行二进制化,从低位到高位
{
if(b&1) res = res *a %p;
b>>=1;
a=a*a%p;
}
return res;
}
int a[N],b[N],c[N];
int d[N];
void solve(){
int n;cin >> n;
//memset(d,0,sizeof d);tle
fr(1,i,n+1)cin >> a[i];
fr(1,i,n+1)cin >> b[i];
fr(1,i,n+1)cin >> c[i];
fr(0,i,n+1)p[i] = i;
fr(0,i,n+1)d[i] = 0;
for(int i = 1;i <= n;i ++){
int px = find(a[i]),py = find(b[i]);
if(px != py){
p[px] = py;
}
}
long long ans = 1;
int cnt = 0;
for(int i = 1;i <= n;i ++){
if(a[i] == b[i])continue;
else{
int temp = find(a[i]);
if(!d[temp])d[temp] = 2,cnt ++;
if(c[i] && d[temp] == 2)d[temp] = 1,cnt --;
}
}
ans = qmi(2,cnt,mod);
cout << ans << endl;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int T;cin >> T;
while(T--){
solve();
}
return 0;
}
题意:无限大的密铺六边形,放任意条(0,60,120)直线,组成最多的三角形的数量(三角形最小)
- 贪-
- 二分
思路:画图,找出每条边放置增加边数最多的情况
如图所示,放完三条边后,看第四条边怎么放使三角形增加数量最多,显然第三条红色水平线增加最多(四个,大三角不算)
可以发现,以此类推,每条边增加最多的数量为——不同类型直线数量和 * 2
具体细节见代码
#include<bits/stdc++.h>
#define debug0(x) cout << endl << "debug0: " << x << endl
#define fr(t, i, n) for (int i = t; i < n; i++)
#define first fi
#define second se
using namespace std;
typedef long long LL;
typedef pair<int,int> PII;
const int N = 4e4;
LL a[N];
void solve(int t){
int n;cin >> n;
cout << (lower_bound(a+1,a+t,n) - a) << endl;//找第一个大于等于他的数的下标
}
int main()
{
/*
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
*/
int T;cin >> T;
LL sum = 0;
int cnt[3] = {0,0,0};
int k = 0,t = 1;
while(sum <= 1e9){
sum += (cnt[(k+1) % 3] + cnt[(k+2) % 3])*2;
cnt[k]++;
a[t++] = sum;
k = (k+1)%3;
}
//cout << t << endl;38731是最多的,在1e9的范围内
while(T--){
solve(t);
}
return 0;
}