兰州大学第一届『飞马杯』程序设计竞赛(同步赛)
环形取数,取n个 可以正取也可以逆取,第一个取的贡献n次,第二个n-1,第n个1次。
长的很像前缀和,然后递推一下,每次算上新的,利用前缀和改一下。
逆取直接sum*(n+1)-正取就好
#include <iostream> #include <cstring> #include <cstdio> #include <string> #include <algorithm> #include <queue> #include <set> using namespace std; typedef long long LL; typedef pair<int, int>PII; LL a[500010]; int t, n; int main() { scanf("%d", &t); while (t--) { scanf("%d", &n); LL sum, sum1, sum2, ans; sum = sum1 = sum2 = 0; ans = 0x3f3f3f3f; for (int i = 1; i <= n; i++) { scanf("%d", &a[i]); sum += a[i];//a1+a2+a3+a4+a5 sum1 += i * a[i]; sum2 += (n - i + 1) * a[i]; } for (int i = n; i >= 1; i--) { sum1 += sum - n * a[i]; ans = min(ans, sum1); } for (int i = 1; i <= n; i++) { sum2 += sum - n * a[i]; ans = min(ans, sum2); } printf("%lld\n", ans); } return 0; }
模拟,如果一个死亡的的细胞周围恰好有 333 个活的细胞,那么下一个回合时,这个细胞的状态将转为“生”
如果一个存活的的细胞周围活细胞的数量大于 333 或小于 222,那么下一个回合时,这个细胞的状态将转为“死”
其他情况下,细胞的存活状态不变
#include <iostream>
using namespace std;
const int N=110;
int t,n,k,a[N][N],now[N][N],s[N][N],ans, di[]= {-1,-1,-1,0,0,1,1,1},dj[]= {-1,0,1,1,-1,-1,0,1}; //模拟题用到的方向数组,遍历八个方向
bool Check() { for(int i=0; i<n; i++)//检查是否进入周期 for(int j=0; j<n; j++)//将a和now中的元素进行比较 if(a[i][j]!=now[i][j]) return false; return true; } void Evolve() { for(int i=0; i<n; i++) for(int j=0; j<n; j++) s[i][j]=0;//用来记录周围有活细胞的个数 for(int i=0; i<n; i++) for(int j=0; j<n; j++) if(now[i][j])//它是活细胞 for(int k=0; k<8; k++)//使八个方向都进行记录 s[(i+di[k]+n)%n][(j+dj[k]+n)%n]++; for(int i=0; i<n; i++) for(int j=0; j<n; j++)//为新的一轮赋值 if(s[i][j]==3) now[i][j]=1; else if(s[i][j]<2||s[i][j]>3) now[i][j]=0; }
int main() { scanf("%d",&t); while(t--) { ans=0; scanf("%d%d",&n,&k); for(int i=0; i<n; i++) for(int j=0; j<n; j++) { scanf("%d",&a[i][j]);//a为初始状态 now[i][j]=a[i][j];//now为改变后的状态 } do { Evolve();//进行一轮演变 ans++; } while(!Check()&&--k);//如果相同或回合次数结束,终止演变 if(k) printf("YES\n%d\n",ans); else printf("NO\n"); } return 0; }