面包人(van)
【题目描述】
小 W 为了对抗小 C 的骑士阵, 叫来了一车面包人来攻打他。由
于小 W 的后台很硬,他叫来的这一车总共有 n 个面包人,从 1~n 编
号。但小 C 很快就摸清了这车面包人的实力,他发现他们的实力跟
他们的编号以及编号的因数个数有着千丝万缕的关系。 假设τ (x)为 x
的因数个数,如果对于编号为 x 的面包人,满足任意编号比他小的面
包人 y, 都有τ (y)<τ (x),那么编号为 x 的面包人的实力就强于所有
编号比他小的面包人,否则他的实力就弱于所有编号比他小的面包
人。现在小 C 希望知道最强的和最弱的面包人的编号。
【输入数据】
输入只有一行, 一个正整数 n,表示面包人的个数。
【输出数据】
输出只有一行, 两个正整数,分别表示最强的和最弱的面包人编
号,两个数之间用空格隔开。
【样例输入】
10
【样例输出】
6 10
【数据范围】
对于 8%的数据, n<=10;
对于 32%的数据, n<=10^5;
另外 8%的数据, n 为质数;
对于 100%的数据, 1<=n<=2*10^9。
【样例解释】
1~10 的因数个数分别是 1,2,2,3,2,4,2,4,3,4。
所以实力排序从弱到强为: 10<9<8<7<5<3<1<2<4<6。
PS:若 x=A^a+B^b+…+N^n.(A、B…均为质数)
那么x的因数个数为 (a+1)*(b+1)*…*(n+1)
题解:首先,我们发现,因数最多的数一定是若干质数的积,且数据范围内所用到的质数很少,那么,我们暴力dfs枚举所用的因数即可。
代码如下:
1 #include<cstdio> 2 #include<iostream> 3 using namespace std; 4 int n,pr[10]={2,3,5,7,11,13,17,19,23,29},maxs,ans; 5 void dfs(long long x,int cnt,int num){ 6 if(maxs<cnt) maxs=cnt,ans=x; 7 if(maxs==cnt&&x<ans) ans=x; 8 if(maxs>cnt&&x>ans) return; 9 int sum=0; 10 while(x*pr[num]<=n){ 11 x*=pr[num]; 12 sum++; 13 dfs(x,cnt*(sum+1),num+1); 14 } 15 } 16 int main() 17 { 18 freopen("van.in","r",stdin); 19 freopen("van.out","w",stdout); 20 scanf("%d",&n); 21 if(n==1){printf("1 1");return 0;} 22 dfs(1,1,0); 23 printf("%d %d",ans,ans==n?n-1:n); 24 return 0; 25 }
寻呼机(pager)
【题目描述】
小 H 和小 S 现在都居住在 B 城, B 城地图可以看做是一个 n*n
的网格图,小 H 住在(1,1),小 S 住在(n,n)。 B 城的通讯设施十分发达,
每一个格子中都建有一座类型为 cij 的通讯塔。 位于(i,j)的通讯塔对于
消息进行处理后只能将消息传输给位于(i+1,j)或(i,j+1)的通讯塔。 一
天,小 H 通过传呼机给小 S 发了一道长度为 n-1 的消息。 所以消息依
次会经历 n-1 道加密、 1 道中枢处理和 n-1 道解密, 每个格子负责 1
道处理,所以一共会经过 2n-1 个格子;根据加密解密原则,每一次
解密会解开最后一次未被解密的加密,且该解密类型必须和对应的那
一次加密类型相同,具体表现为对应的两个格子类型 cij 相同。满足
以上条件能把信息成功从(1,1)传输到(n,n)的路径,称为合法信息通
路。等待回复的时间很漫长,小 H 端详着 B 城地图,他希望知道不
同的合法信息通路有多少种。
【输入数据】
第一行一个正整数 n, 表示 B 城大小。
接下来 n 行,每行 n 个整数,表示 B 城每个格子的类型 cij。
【输出数据】
输出一个整数,表示合法信息通路的种数, 答案对 10^9+7 取模。
【样例输入】
3
1 2 3
1 1 2
2 1 1
【样例输出】
4
【数据范围】
对于 10%的数据, n<=10;
对于 30%的数据, n<=50;
对于 50%的数据, n<=100;
另外 5%的数据,所有的 cij均相等;
另外 10%的数据, 0<=cij<=1;
对于 100%的数据, 1<=n<=500, 0<=cij<=10^9。
【样例解释】
4 条路径:
① (1,1)-(1,2)-(1,3)-(2,3)-(3,3): 12321;
② (1,1)-(1,2)-(2,2)-(2,3)-(3,3): 12121;
③ (1,1)-(2,1)-(2,2)-(3,2)-(3,3): 11111;
④ (1,1)-(2,1)-(3,1)-(3,2)-(3,3): 11211。
题解:因为xy特征值相加相同的数必在同一斜行,n^3 dp即可,内存不够所以用滚动数组。
变量声明:f[i][j][k](i从0开始)表示第i斜行第j行的数到第n-2-i斜行第k行的数的方案数。
状态转移方程:f[i][j][k]=f[i-1][j][k]+f[i-1][j-1][k]+f[i-1][j][k+1]+f[i-1][j-1][k+1]
代码如下:
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #define ljm 1000000007 5 using namespace std; 6 int n,s[505][505],I=1; 7 long long f[2][505][505],ans; 8 int main() 9 { 10 freopen("pager.in","r",stdin); 11 freopen("pager.out","w",stdout); 12 scanf("%d",&n); 13 for(int i=1;i<=n;i++) 14 for(int j=1;j<=n;j++) scanf("%d",&s[i][j]); 15 if(s[1][1]!=s[n][n]){printf("0");return 0;} 16 f[0][1][n]=1; 17 for(int i=1;i<=n-1;i++){ 18 memset(f[I],0,sizeof(f[I])); 19 for(int j=1;j<=i+1;j++) 20 for(int k=n-i;k<=n;k++){ 21 int p1=i+2-j,p2=2*n-i-k; 22 if(s[j][p1]==s[k][p2]) 23 f[I][j][k]=(f[I^1][j-1][k]+f[I^1][j][k+1]+f[I^1][j-1][k+1]+f[I^1][j][k])%ljm; 24 } 25 I^=1; 26 }I^=1; 27 for(int i=1;i<=n;i++) ans=(ans+f[I][i][i])%ljm; 28 printf("%lld",ans%ljm); 29 return 0; 30 }
疏散(nuclear)
【题目描述】
没有什么是一颗核弹解决不了的,如果有,那就来两颗。
你的营地现在正在接受小 C 的核弹轰炸,心灵控制仪矿场啥的估
计都要没了。你现在需要紧急疏散你各个建筑物里的部队,你的营地
里共有 n 个建筑,疏散第 i 个建筑里的部队需要 ti 的时间, 在同一时
刻内,你只能疏散一个建筑内的部队。然而你已经通过侦查部队知道
了小 C 对于你的营地的轰炸方案,你的第 i个建筑会在 si时刻被炸毁,
如果一个建筑里的部队正在疏散或还未疏散时建筑被炸毁,那么这个
建筑里的部队就不能算被成功疏散,为了能够再积蓄兵力与小 C 一
战,你希望疏散尽量多的建筑里的部队。
【输入数据】
第一行一个正整数 n,表示建筑个数。
接下来 n 行,每行两个整数, ti 和 si。含义如题中所述。
【输出数据】
输出只有一行,表示最多能疏散多少建筑里的部队。
【样例输入】
3
1 1
10 101
100 101
【样例输出】
2
【数据范围】
对于 10%的数据, n<=10;
对于 20%的数据, n,ti,si<=2000;
对于 50%的数据, n,ti,si<=20000
另外 10%的数据,满足所有 si都相等。
另外 20%的数据,满足所有 ti都相等。
对于 100%的数据, 1<=n<=300000, 0<=si,ti<=10^9。
【样例解释】
先疏散第 1个建筑, 再疏散第 2或第 3 个建筑。
据, n<=10;对于 20%的数据, n,ti,si<=2000;对于 50%的数据, n,ti,si<=20000另外 10%的数据,满足所有 si都相等。另外 20%的数据,满足所有 ti都相等。对于 100%的数据, 1<=n<=300000, 0<=si,ti<=10^9。【样例解释】先疏散第 1个建筑, 再疏散第 2或第 3 个建筑。
题解:首先考虑贪心,我们把建筑按摧毁时间从小到大排序,若能疏散就疏散,若无法疏散就与已疏散的建筑所花时间最多的作比较,若小则替换,我们可以用堆维护这个最大值。
代码如下:
1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<queue> 5 #define MN 300005 6 using namespace std; 7 int n,ans; long long sum; 8 struct node{int t,s;}a[MN]; 9 priority_queue<int> pq; 10 bool cmp(node x,node y){return x.s<y.s;} 11 int main() 12 { 13 freopen("nuclear.in","r",stdin); 14 freopen("nuclear.out","w",stdout); 15 scanf("%d",&n); 16 for(int i=1;i<=n;i++) scanf("%d%d",&a[i].t,&a[i].s); 17 sort(a+1,a+1+n,cmp); 18 for(int i=1;i<=n;i++){ 19 if(sum+a[i].t<=a[i].s) ans++,sum+=a[i].t,pq.push(a[i].t); 20 else if(!pq.empty()&&a[i].t<pq.top()){ 21 sum+=a[i].t-pq.top(); 22 pq.pop(); pq.push(a[i].t); 23 } 24 } 25 printf("%d",ans); 26 return 0; 27 }