10.11NOIP模拟题(3)
/* 可以看出,对于一段区间[L,R]如果统计了答案 若a[L]<a[R],那么当右端点往左移时答案不会更优,a[R]>a[L]同理 所以两个指针分别从头尾往中间扫那边小移哪边即可。 */ #include<bits/stdc++.h> #define N 1000007 #define ll long long using namespace std; ll a[N]; ll n,m,ans,cnt; int main() { freopen("w.in","r",stdin); freopen("w.out","w",stdout); scanf("%lld",&n); for(int i=1;i<=n;i++) scanf("%lld",&a[i]); int L=1,R=n; while(L<=R) { ll res=(R-L+1)*min(a[L],a[R]); ans=max(ans,res); if(a[L]>=a[R]) R--; else L++; } cout<<ans<<endl; return 0; }
/* 发现算来算去所有数的二进制1的个数和位置不会变。 两个数and 或 or只是把他们的二进制位的1聚拢到一个数上。 若两个数为a,b,假设他们进行一次操作后变为(a+x),(b-x),则a>b 那么(a+x)^2+(b-x)^2=a^2+b^2+2x(x+a-b)>a^2+b^2 说明这种“聚拢”操作后平方和会变大 所以把所有数的二进制位1统计下来后尽可能的对分给一个数即可。 */ #include<bits/stdc++.h> #define mod 998244353 #define N 10005 using namespace std; int n,x; int cnt[N]; int main() { freopen("s.in","r",stdin); freopen("s.out","w",stdout); scanf("%d",&n); for (int i=1;i<=n;i++) { scanf("%d",&x); for (int j=0;j<32;j++) if (x & (1<<j)) cnt[j]++; } unsigned long long ans=0; for(int i=0;i<n;i++) { x=0; for(int j=0;j<32;j++) if (cnt[j]) x |=(1<<j),cnt[j]--; ans+=(unsigned long long)(x)*x%mod;; } cout<<ans%mod; return 0; }
#include<bits/stdc++.h> #define N 30 #define ll long long #define mod 1000000007 #define opt 99999 using namespace std; int n,m,k,lim; ll ans; int dx[4]={0,0,1,-1}; int dy[4]={1,-1,0,0}; int vis[N][N],f[N][N]; inline ll read() { int x=0,f=1;char c=getchar(); while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();} return x*f; } bool can(int x,int y) { if(vis[x][y]==-1) return false; for(int i=max(1,y-2);i<=min(y+2,m);i++) if(vis[x][i]>=opt) return false; for(int i=max(1,x-2);i<=min(n,x+2);i++) if(vis[i][y]>=opt) return false; if(vis[x-1][y-1]>=opt || vis[x-1][y+1]>=opt) return false; if(vis[x+1][y+1]>=opt || vis[x+1][y-1]>=opt) return false; return true; } void update(int x,int y) { vis[x][y]=opt; for(int i=max(1,y-2);i<=min(y+2,m);i++) if(vis[x][i]!=-1)vis[x][i]++; for(int i=max(1,x-2);i<=min(n,x+2);i++) if(vis[i][y]!=-1)vis[i][y]++; if(x-1 && y-1 && vis[x-1][y-1]!=-1) vis[x-1][y-1]++; if(x-1 && y+1<=m && vis[x-1][y+1]!=-1) vis[x-1][y+1]++; if(x+1<=n && y-1 && vis[x+1][y-1]!=-1) vis[x+1][y-1]++; if(x+1<=n && y+1<=m && vis[x+1][y+1]!=-1) vis[x+1][y+1]++; } void _update(int x,int y) { vis[x][y]=0; for(int i=max(1,y-2);i<=min(y+2,m);i++) if(vis[x][i]>0)vis[x][i]--; for(int i=max(1,x-2);i<=min(n,x+2);i++) if(vis[i][y]>0)vis[i][y]--; if(vis[x-1][y-1]>0)vis[x-1][y-1]--; if(vis[x-1][y+1]>0)vis[x-1][y+1]--; if(vis[x+1][y-1]>0)vis[x+1][y-1]--; if(vis[x+1][y+1]>0)vis[x+1][y+1]--; f[x][y]=0; } void dfs(int x,int y,int L) { if(L==0) { ans++;ans%=mod; return; } for(int xx=x;xx<=n;xx++) for(int yy=1;yy<=m;yy++) { if(f[xx][yy]) continue; if(vis[xx][yy]<opt && can(xx,yy) && !f[xx][yy]) { update(xx,yy); f[xx][yy]=1; dfs(xx,yy,L-1); _update(xx,yy);//dfs(xx,yy,L); } } } int main() { freopen("l.in","r",stdin); freopen("l.out","w",stdout); int x,y;ans=0; n=read();m=read();k=read(); for(int i=1;i<=n;i++) { x=read();y=read(); vis[x][y]=-1; } lim=n*m-k; while(lim--) { memset(f,0,sizeof f); f[1][1]=1; dfs(1,1,lim); } ans%=mod;cout<<ans<<endl; return 0; }
#include <cstdio> #include <cstring> #include <vector> const int MAXN = 15; const int MOD = 1e9 + 7; int m; inline unsigned int getBit(int i) { return 1u << i; } inline bool isValidLine(unsigned int s) { return !((s & (s << 1)) || (s & (s << 2))); } inline bool isValidTwoLines(unsigned int a, unsigned int b) { return !((a & (b << 1)) || (a & (b >> 1)) || (a & b)); } inline bool isValidThreeLines(unsigned int a, unsigned int b, unsigned int c) { return !(a & c) && isValidTwoLines(a, b)/* && isValidTwoLines(b, c)*/; } int main() { freopen("l.in", "r", stdin); freopen("l.out", "w", stdout); int n, k; scanf("%d %d %d", &n, &m, &k); unsigned int ban[n + 1]; memset(ban, 0, sizeof(ban)); while (k--) { int i, j; scanf("%d %d", &i, &j); ban[i] |= 1 << (j - 1); } std::vector<unsigned int> validStates; unsigned int maxS = 1 << m; for (int i = 0; i < maxS; i++) { if (isValidLine(i)) { validStates.push_back(i); } } // f[i][state of line i - 1][state of line i] = count long long f[n + 1][validStates.size()][validStates.size()]; memset(f, 0, sizeof(f)); for (int a = 0; a < (int)validStates.size(); a++) f[0][0][a] = 1; long long ans = 0; for (int i = 1; i <= n; i++) { for (int c = 0; c < (int)validStates.size(); c++) { if (ban[i] & validStates[c]) continue; for (int b = 0; b < (i <= 1 ? 1 : (int)validStates.size()); b++) { if (!isValidTwoLines(validStates[b], validStates[c])) continue; if (ban[i - 1] & validStates[b]) continue; for (int a = 0; a < (i <= 2 ? 1 : (int)validStates.size()); a++) { if (!isValidThreeLines(validStates[a], validStates[b], validStates[c])) continue; if (a && (ban[i - 2] & validStates[a])) continue; (f[i][b][c] += f[i - 1][a][b]) %= MOD; } if (i == n) (ans += f[i][b][c]) %= MOD; } } } printf("%lld\n", ans); }
暂时放弃 先做完互不侵犯king再来写这道题
折花枝,恨花枝,准拟花开人共卮,开时人去时。
怕相思,已相思,轮到相思没处辞,眉间露一丝。