I 限制不互素对的排列
1.题意:
2.题解:
3.ac代码:
#include<bits/stdc++.h>
const int N=1e5+10;
using namespace std;
int a[N];
int tot;
int main(){
int n,k;
cin>>n>>k;
if(n<6&&k==n/2){
cout<<-1<<endl;
return 0;
}
if(k==0){
for(int i=1;i<=n;i++)
cout<<i<<" ";
return 0;
}
if(k<n/2){
for(int i=2;i<=2*k+2;i+=2){
cout<<i<<" ";
}
for(int i=1;i<=2*k+1;i+=2){
cout<<i<<" ";
}
for(int i=2*k+3;i<=n;i++){
cout<<i<<" ";
}
}
if(k==n/2){
int t=k;
while(t%2==0){
t=t/2;
}
if(t==1){
for(int i=2;i<=2*k;i+=2){
if(i!=6) cout<<i<<" ";
}
cout<<6<<" "<<3<<" ";
for(int i=1;i<=2*k-1;i+=2){
if(i!=3)
cout<<i<<" ";
}
}else{
for(int i=2;i<=2*k;i+=2)
cout<<i<<" ";
cout<<t<<" ";
for(int i=1;i<=2*k-1;i+=2){
if(i!=t)
cout<<i<<" ";
}
}
for(int i=2*k+1;i<=n;i++){
if(i!=k) cout<<i<<" ";
}
}
cout<<endl;
}
C 红和蓝
1.题意:
2.题解:
对树进行两次深度搜索,将每一个节点和父节点变成同色,当该点未被赋色且父节点已经有颜色时不成立
3.ac代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e6+10;
int h[N],e[N],ne[N],idx;
int col[N];
void add(int a,int b){
e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
char f[N];
int flag;
int tot;
void dfs(int s,int u){
int son=0;
for(int i=h[s];i!=-1;i=ne[i]){
int j=e[i];
if(j!=u){
son++;
dfs(j,s);
}
}
if(son==0||col[s]==0){
if(col[u]!=0){
flag=1;return;
}
col[s]=col[u]=++tot;
}
}
void dfs1(int s,int u){
for(int i=h[s];i!=-1;i=ne[i]){
int j=e[i];
if(j!=u){
if(col[s]==col[j])
f[j]=f[s];
else
f[j]=f[s]^1;
dfs1(j,s);
}
}
}
int main(){
int n;
cin>>n;
int a,b;
// memset(col,-1,sizeof col);
memset(h,-1,sizeof h);
memset(ne,-1,sizeof ne);
for(int i=1;i<n;i++){
cin>>a>>b;
add(a,b);add(b,a);
}
if(n&1){
cout<<-1<<endl;return 0;
}
dfs(1,0);
if(col[0]!=0) flag=1;
if(flag==1){
cout<<-1<<endl;return 0;
}else{
//f[1]=1;
dfs1(1,0);
for(int i=1;i<=n;i++){
if(f[i]==1) cout<<'R';
else cout<<'B';
}
cout<<endl;
}
}
D 点一成零
1.题意:
2.题解:
需要用到 并查集+逆元+快速幂。
查找连通块的大小及个数,我一开始想用dfs(之前写过找最大连通块就是用dfs写的)但是用了并查集,显然不用再用dfs,我dfs函数里头一开始遍历该点周围点的时候,dfs思想,深搜每一个邻边的点,但是显然不需要,因为并查集已经记录了,所以一开始内存超限错了
把操作分为两种,一种是原来就是1的,另一种是变为1的
显然原来是1的就输出原答案即可,
第2种,变1,就将该块看作新加入的一个连通块,然后遍历周围每一个点看是否可以联通,可以就合并
在做的时候,这块公式没整明白:
首先:res=cnt!(连通块数的阶乘) X S(所有连通块大小乘积)
对于每一个新加入的块,都将其作为一个单独的,更新res,即cnt++,res=rescnt%mod
遍历周围,如果需要合并,显然cnt–,那么cnt!也要除以当前cnt,即res=res(cnt的逆元)
同时块的大小也有变化,块a和块b变成了块(a+b),所以res也要除以块a块b的大小再乘上块(a+b)的大小,注意这里都是原来的块a块b的大小,完成对res的运算再合并sz[a],sz[b],否则就不是原来的大小了
一开始以为要用二维并查集,后来发现只需要把二维坐标变成一维的就ok了
3.ac代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=1e9+7;
const int N=1e6+10;
int f[N];
int sz[N];
int dx[4]={0,1,0,-1};
int dy[4]={1,0,-1,0};
char str[510][510];
int cnt;
int n;
//(i-1)*n+j
void init(int n){
for(int i=1;i<=n;i++){
f[i]=i;sz[i]=1;
}
}
int get(int a){
if(a==f[a]){
return f[a];
}
return f[a]=get(f[a]);
}
void merge(int x,int y){
x=get(x);y=get(y);
if(x!=y){
f[x]=y;
sz[y]+=sz[x];
}
}
void dfs(int x,int y){
for(int i=0;i<4;i++){
int ax=x+dx[i];
int ay=y+dy[i];
if(str[ax][ay]=='0') continue;
if(ax>0&&ax<=n&&ay>0&&ay<=n){
merge((ax-1)*n+ay,(x-1)*n+y);
}
}
}
ll kmi(ll a,ll b,ll mod){
ll res=1;
while(b){
if(b&1) res=res*a%mod;
b>>=1;
a=a*a%mod;
}
return res%mod;
}
ll ni(ll a){
return kmi(a,mod-2,mod);
}
int main(){
cin>>n;
init(n*n);
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
cin>>str[i][j];
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(str[i][j]=='1') dfs(i,j);
}
}
ll s=1;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(f[(i-1)*n+j]==(i-1)*n+j&&str[i][j]=='1'){
cnt++;
s=s*(ll)sz[(i-1)*n+j]%mod;
}
}
}
ll res=1;
for(int i=1;i<=cnt;i++){
res=res*(i)%mod;
}
res=s*res%mod;
int k;
cin>>k;
int x,y;
for(int i=1;i<=k;i++){
cin>>x>>y;
x=x+1;y=y+1;
int b=(x-1)*n+y;
if(str[x][y]=='1'){
cout<<res<<endl;
continue;
}
cnt++;
res=res*cnt%mod;//!!!新加一个块就立刻x上去
str[x][y]='1';
for(int i=0;i<4;i++) {
int ax = x + dx[i];
int ay = y + dy[i];
if(ax<=0||ay<=0||ax>n||ay>n||str[ax][ay]!='1') continue;
int a = (ax - 1) * n + ay;
b = get(b);
a = get(a);
if (a != b) {
res=res*ni(cnt)%mod;
res=res*ni(sz[a])%mod;
res=res*ni(sz[b])%mod;
res=res*(sz[a]+sz[b])%mod;
merge(a,b);
cnt--;
}
}
cout<<res%mod<<endl;
}
}
J 一群小青蛙呱蹦呱蹦呱
1.题意:
2.题解:
留下的数肯定由至少两个不同的质数乘积组成
由此可知最小公倍数由p1a1p2a2…pnan构成,且a1,a2,an都取最大,求<n的含有p1,的不被删除的数最大拥有多少个p1,p2,…
a1最大是log2 n/3,因为必须最少有个3,而3,5,7,。。。都是log i n/2即可,前面有2
3.ac代码:
不知道是不是牛客有bug,交不上去了
#include <bits/stdc++.h>
using namespace std;
const int N = 180000010,mod = 1e9 + 7;
typedef long long ll;
ll primes[N],idx;
bool st[N];
ll qmi(ll a,ll b,ll mod)
{
ll res = 1;
while(b)
{
if(b & 1)
{
res = res * a % mod;
}
a = a * a % mod;
b >>= 1;
}
return res;
}
int main()
{
ll n,ans = 1;
cin >> n;
for(int i = 2;i <= n / 2;i++)
{
if(!st[i])
{
primes[idx++] = i;
if(i == 2)
{
ll k = floor(log(n / 3) / log(2));
ans = ans * qmi(2,k,mod) % mod;
}
else
{
ll k = floor(log(n / 2) / log(i));
ans = ans * qmi(i,k,mod) % mod;
}
}
for(int j = 0;i * primes[j] <= n / 2 && j < idx;j++)
{
st[primes[j] * i] = true;
if(i % primes[j] == 0)
{
break;
}
}
}
if(ans == 1) puts("empty");
else cout << ans << endl;
return 0;
}
A 串
1.题意:
2.题解:
3.ac代码:
#include<bits/stdc++.h>
#include<string>
using namespace std;
typedef long long ll;
const int N=1e6+10;
const int mod=1e9+7;
ll f[N][4];
ll quick_pow(ll a,ll b){
ll res=1;
while(b){
if(b&1) res=res*a%mod;
b>>=1;
a=a*a%mod;
}
return res%mod;
}
// int main(){
// int n;
// cin>>n;
// ll res=0;
// // res+=quick_pow(26, n)%mod;
// res+=quick_pow(25, n)%mod;
// for(int i=1;i<=n;i++){
// res=(res+quick_pow(25, n-1))%mod;
// }
// ll sum=quick_pow(26, n)%mod;
// sum=sum-res;
// if(sum<0) sum=(sum+mod)%mod;
// cout<<sum<<endl;
// }
ll res=0;
int main(){
int n;
cin>>n;
f[1][0]=25;//无u
f[1][1]=1;//有u无s
f[1][2]=0;//有us
for(int i=2;i<=n;i++){
f[i][0]=f[i-1][0]*25%mod;
f[i][1]=(f[i-1][1]*25%mod+f[i-1][0]%mod)%mod;
f[i][2]=(f[i-1][2]*26%mod+f[i-1][1]%mod)%mod;
res=(res+f[i][2])%mod;
}
cout<<res<<endl;
}
E 三棱锥之刻
1.题意:
2.题解:
!!!终于搞出来了,呜呜呜呜,细心细心再细心!!
注意求角度时都是换成pi,度数!=对应的整数,要变成pi形式的,注意扇形面积=sitarr,没有1/2!!!
3.ac代码:
#include<bits/stdc++.h>
#include<math.h>
#include<string>
using namespace std;
const int N=1e6+10;
string s,t;
const double pi=2*asin(1.0);
int main(){
double a,r;
double ans=0;
cin>>a>>r;
double d=sqrt(6.0)/12.0*a;
double y=sqrt(6.0)/4.0*a;
double x=sqrt(2.0)/4.0*a;
if(r<=d){
cout<<ans<<endl;
return 0;
}else if(r>d&&r<=x){
ans=pi*(r*r-d*d);
cout<<4*ans<<endl;
}else if(r>x&&r<y){
double r1=r*r-a*a/24;
double d1=sqrt(3.0)/6.0*a;
double st=pi/3-acos(d1/sqrt(r1));
ans=st*r1+sqrt(r1-1.0/12*a*a)*d1;
cout<<12*ans<<endl;
}else {
cout<<sqrt(3.0)*a*a<<endl;
}
}
`