链接:戳这里
题意:子集的抑或总和
思路:由于n>1的时候都是偶数出现的 为0
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<string> #include<vector> #include <ctime> #include<queue> #include<set> #include<map> #include<stack> #include<cmath> #define mst(ss,b) memset((ss),(b),sizeof(ss)) #define maxn 0x3f3f3f3f #define MAX 1000100 ///#pragma comment(linker, "/STACK:102400000,102400000") typedef long long ll; typedef unsigned long long ull; #define INF (1ll<<60)-1 using namespace std; int T; int n,a[100100]; int main(){ scanf("%d",&T); while(T--){ scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]); if(n==1) cout<<a[1]<<endl; else cout<<0<<endl; } return 0; }
1
题意:给出一个字符串,要求该字符串可以组成多少种回文串
思路:回文串左右两边都一样,所以只需要对(n/2)排列组合就可以了,这里取模的话注意有除法,我用的费马小
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<string> #include<vector> #include <ctime> #include<queue> #include<set> #include<map> #include<stack> #include<cmath> #define mst(ss,b) memset((ss),(b),sizeof(ss)) #define maxn 0x3f3f3f3f #define MAX 1000100 ///#pragma comment(linker, "/STACK:102400000,102400000") typedef long long ll; typedef unsigned long long ull; #define INF (1ll<<60)-1 #define mod 1000000007 using namespace std; ll fac[100100]; ll ppow(ll k,ll n) { ll c=1; while(n) { if(n%2) c=(c*k)%mod; k=(k*k)%mod; n>>=1; } return c; } ll C(ll a,ll b) { return (((fac[b]*ppow((fac[a]*fac[b-a])%mod,mod-2)))%mod)%mod; } int T; string s; ll a[30]; int main(){ scanf("%d",&T); fac[0]=1; for(int i=1;i<1010;i++) fac[i]=(fac[i-1]*i)%mod; while(T--){ cin>>s; mst(a,0); int n=s.size(); for(int i=0;i<n;i++){ int x=s[i]-'a'; a[x+1]++; } int num=0,sum=0; for(int i=1;i<=26;i++){ if(a[i]%2==0) { a[i]/=2; continue; } if(a[i]%2==1) { if(num==0) a[i]/=2; num++; } } if(num>1) cout<<0<<endl; else { ll ans=1; int L=n/2; for(int i=1;i<=26;i++){ if(a[i]){ ll tmp=C(a[i],L); ///ll tmp=CCC(L,a[i]); L-=a[i]; ans*=tmp; ans%=mod; } } printf("%I64d\n",ans); } } return 0; }
题意:中国和印度需要联通,但是上面有山峰阻挡,山峰随着时间的推移会越来越多,问在哪一个时间两国无法联通
思路:二分时间,然后用并查集去处理0和(n*m+1)是否联通,(1~n*m)是图上的点,显然并查集很好处理连通块的问题
O( n*m*log(n*m) )
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<string> #include<vector> #include <ctime> #include<queue> #include<set> #include<map> #include<stack> #include<cmath> #define mst(ss,b) memset((ss),(b),sizeof(ss)) #define maxn 0x3f3f3f3f #define MAX 1000100 ///#pragma comment(linker, "/STACK:102400000,102400000") typedef long long ll; typedef unsigned long long ull; #define INF (1ll<<60)-1 using namespace std; int T,n,m,q; string s[555]; int a[555][555]; int x[555*555],y[555*555]; int xx[4]={-1,0,1,0}; int yy[4]={0,1,0,-1}; int vis[555][555]; int fa[250010]; int find(int x){ if(x!=fa[x]) fa[x]=find(fa[x]); return fa[x]; } void Union(int x,int y){ int xx=find(x); int yy=find(y); if(xx!=yy) fa[xx]=yy; } bool judge(){ mst(vis,0); for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ vis[i][j]=a[i][j]; } } for(int i=0;i<=n*m+1;i++) fa[i]=i; for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ if(vis[i][j]) continue; for(int k=0;k<4;k++){ int X=i+xx[k]; int Y=j+yy[k]; if(Y<1 || Y>m) continue; if(vis[X][Y]) continue; if(X==0) Union(0,(i-1)*m+j); else if(X==n+1) Union(n*m+1,(i-1)*m+j); else { Union((i-1)*m+j,(X-1)*m+Y); } } } } if(find(0)==find(n*m+1)) return true; return false; } bool solve(int k){ for(int i=1;i<=k;i++) a[x[i]][y[i]]=1; int t=0; if(judge()) t=1; for(int i=1;i<=k;i++) a[x[i]][y[i]]=0; if(t) return true; return false; } int main(){ scanf("%d",&T); while(T--){ scanf("%d%d",&n,&m); mst(a,0); for(int i=0;i<n;i++) cin>>s[i]; for(int i=0;i<n;i++){ for(int j=0;j<m;j++){ if(s[i][j]=='1') a[i+1][j+1]=1; else a[i+1][j+1]=0; } } scanf("%d",&q); for(int i=1;i<=q;i++){ scanf("%d%d",&x[i],&y[i]); x[i]++; y[i]++; } if(solve(q)){ cout<<-1<<endl; continue; } int l=1,r=q,mid,ans=0; while(l<r){ mid=(l+r)/2; if(solve(mid)) l=mid+1; else r=mid,ans=mid; } cout<<ans<<endl; } return 0; }
题意:给出一维长度n,格子上有m个炸弹,要求自己设定炸弹的l,r使所有炸弹爆炸的总乘积最大
思路:看了卿神的思路,哎,赤裸裸的暴力,感觉复杂度就是O(n*m) 常数大一点好像
dp[i][j] 表示第i个炸弹炸到j格子的当前最大总乘积
dp[i][j]=max(dp[i][j],(j-k)*dp[i-1][k]) 枚举每i-1个炸弹能炸的长度,其实也就是区间[ a[i-2]+1~a[i-1], a[i-1]+1~a[i] ]
这里加一个炸弹m+1 放在n+2 就是方便计算第m个炸弹炸到n+1之前的最大值
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<string> #include<vector> #include <ctime> #include<queue> #include<set> #include<map> #include<stack> #include<iomanip> #include<cmath> #define mst(ss,b) memset((ss),(b),sizeof(ss)) #define maxn 0x3f3f3f3f #define MAX 1000100 ///#pragma comment(linker, "/STACK:102400000,102400000") typedef long long ll; typedef unsigned long long ull; #define INF (1ll<<60)-1 using namespace std; long double dp[2001][2001]; int n,m; int a[2001]; int main(){ int T; scanf("%d",&T); while(T--){ mst(dp,0); scanf("%d%d",&n,&m); for(int i=1;i<=m;i++) { scanf("%d",&a[i]); a[i]++; } sort(a+1,a+m+1); for(int i=1;i<=a[1];i++) dp[1][i]=1.0; a[++m]=n+2; for(int i=2;i<=m;i++){ for(int j=a[i-1]+1;j<=a[i];j++){ for(int k=a[i-2]+1;k<=a[i-1];k++){ dp[i][j]=max(dp[i][j],(j-k)*dp[i-1][k]); } } } long double ans=floor(1000000.0*log2(dp[m][n+1])); ///cout<<setprecision(0)<<ans<<endl; printf("%.0lf\n",ans); } return 0; }