hdu 6092(一)



Rikka with Subset

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 139    Accepted Submission(s): 49


Problem Description
As we know, Rikka is poor at math. Yuta is worrying about this situation, so he gives Rikka some math tasks to practice. There is one of them:

Yuta has  n  positive  A1An  and their sum is  m . Then for each subset  S  of  A , Yuta calculates the sum of  S

Now, Yuta has got  2n  numbers between  [0,m] . For each  i[0,m] , he counts the number of  i s he got as  Bi .

Yuta shows Rikka the array  Bi  and he wants Rikka to restore  A1An .

It is too difficult for Rikka. Can you help her?  
 

Input
The first line contains a number  t(1t70) , the number of the testcases. 

For each testcase, the first line contains two numbers  n,m(1n50,1m104) .

The second line contains  m+1  numbers  B0Bm(0Bi2n) .
 

Output
For each testcase, print a single line with  n  numbers  A1An .

It is guaranteed that there exists at least one solution. And if there are different solutions, print the lexicographic minimum one.
 

Sample Input
      
2 2 3 1 1 1 1 3 3 1 3 3 1
 

Sample Output
      
1 2 1 1 1
Hint
In the first sample, $A$ is $[1,2]$. $A$ has four subsets $[],[1],[2],[1,2]$ and the sums of each subset are $0,1,2,3$. So $B=[1,1,1,1]$
 

Source

题意:有一个数列 a[] ,长度(n<=50)。b[i] 表示元素和为 i 的集合个数。给你一个数列 b[] ,长度(m<=10000),让你求 a[],并按照其字典序最小输出


显然数字0的数量num[0]为log2(b[0]),数字1的数量num[1]为b[1]/b[0]

设dp[i],表示在当前i没有的情况下,用前面已知数量的数组成数字i共有多少种情况

那么b[i]-dp[i]即为数字i与0进行组合的可能性,则num[i]=(b[i]-dp[i])/b[0]

这里如果直接写的话复杂度为o(m^2)会超时,所以需要剪枝:

  1. if (dp[j] == 0) continue;  
  2. if (num[i] == 0) break;  
if (dp[j] == 0) continue;
if (num[i] == 0) break;
直接将m^2的复杂度降为nm

  1. #include <iostream>  
  2. #include <cstdio>  
  3. #include <cstring>  
  4. #include <cmath>  
  5. #include <algorithm>  
  6. #include <queue>  
  7. #include <map>  
  8. #define ms(a,b) memset(a,b,sizeof(a))   
  9. using namespace std;  
  10. typedef long long ll;  
  11.   
  12. const int maxn = 1e4 + 100;  
  13.   
  14. ll b[maxn];  
  15. int dp[maxn], num[maxn];  
  16.   
  17. int C(int n, int m)  
  18. {  
  19.     int sum = 1;  
  20.     for (int i = n - m + 1; i <= n; i++) sum *= i;  
  21.     for (int i = 1; i <= m; i++) sum /= i;  
  22.     return sum;  
  23. }  
  24.   
  25. int main()  
  26. {  
  27.     int t;  
  28.     scanf("%d", &t);  
  29.     while (t--)  
  30.     {  
  31.         int n, m;  
  32.         scanf("%d%d", &n, &m);  
  33.         ms(dp, 0);  
  34.         ms(num, 0);  
  35.         for (int i = 0; i <= m; i++)  
  36.         {  
  37.             scanf("%lld", &b[i]);  
  38.         }  
  39.         num[0] = log2(b[0]);  
  40.         num[1] = b[1] / b[0];  
  41.         dp[0] = b[0];  
  42.         for (int i = 0; i <= m; i++)  
  43.         {  
  44.             for (int j = m; j >= 0; j--)  
  45.             {  
  46.                 if (dp[j] == 0) continue;  
  47.                 if (num[i] == 0) break;  
  48.                 for (int k = 1; k <= num[i]; k++)  
  49.                 {  
  50.                     if (j + k*i <= m)  
  51.                     {  
  52.                         dp[j + k*i] += dp[j] * C(num[i], k);  
  53.                     }  
  54.                 }  
  55.             }  
  56.             if (i + 1 <= m)  
  57.             {  
  58.                 num[i + 1] = (b[i + 1] - dp[i + 1]) / b[0];  
  59.             }  
  60.         }  
  61.         bool flag = 0;  
  62.         for (int i = 0; i <= m; i++)  
  63.         {  
  64.             for (int j = 1; j <= num[i]; j++)  
  65.             {  
  66.                 if (!flag) printf("%d", i), flag = 1;  
  67.                 else printf(" %d", i);  
  68.             }  
  69.         }  
  70.         puts("");  
  71.     }  
  72.     return 0;  
  73. }  
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <queue>
#include <map>
#define ms(a,b) memset(a,b,sizeof(a)) 
using namespace std;
typedef long long ll;

const int maxn = 1e4 + 100;

ll b[maxn];
int dp[maxn], num[maxn];

int C(int n, int m)
{
	int sum = 1;
	for (int i = n - m + 1; i <= n; i++) sum *= i;
	for (int i = 1; i <= m; i++) sum /= i;
	return sum;
}

int main()
{
	int t;
	scanf("%d", &t);
	while (t--)
	{
		int n, m;
		scanf("%d%d", &n, &m);
		ms(dp, 0);
		ms(num, 0);
		for (int i = 0; i <= m; i++)
		{
			scanf("%lld", &b[i]);
		}
		num[0] = log2(b[0]);
		num[1] = b[1] / b[0];
		dp[0] = b[0];
		for (int i = 0; i <= m; i++)
		{
			for (int j = m; j >= 0; j--)
			{
				if (dp[j] == 0) continue;
				if (num[i] == 0) break;
				for (int k = 1; k <= num[i]; k++)
				{
					if (j + k*i <= m)
					{
						dp[j + k*i] += dp[j] * C(num[i], k);
					}
				}
			}
			if (i + 1 <= m)
			{
				num[i + 1] = (b[i + 1] - dp[i + 1]) / b[0];
			}
		}
		bool flag = 0;
		for (int i = 0; i <= m; i++)
		{
			for (int j = 1; j <= num[i]; j++)
			{
				if (!flag) printf("%d", i), flag = 1;
				else printf(" %d", i);
			}
		}
		puts("");
	}
	return 0;
}


### 杭州电子科技大学操作系统实验概述 Linux内核编译及添加系统调用是杭州电子科技大学操作系统课程中的个重要实验内容[^3]。此实验旨在让学生深入了解Linux系统的内部工作原理以及如何扩展其功能。 #### 实验目标 通过本实验,学生能够掌握以下技能: - 编译完整的Linux内核源码树并安装新构建的内核镜像文件。 - 修改现有的系统调用来创建自定义版本或者新增加新的系统调用接口。 - 使用`gcc`工具链来交叉编译适用于不同架构的目标平台上的可执行程序。 - 测试所编写的新特性是否按预期正常运行。 #### 主要操作步骤 为了完成上述任务,具体的操作流程如下所示: 1. **准备环境** 安装必要的依赖包以支持后续的工作,比如`build-essential`, `libncurses-dev`等开发库。 2. **获取官方发布的稳定版内核源代码** 可以从kernel.org下载最新的稳定发行版本作为基础进行定制化改造。 3. **配置选项设置** 利用菜单驱动式的界面(`make menuconfig`)调整各项参数直至满足需求为止。 4. **实际改动部分——向系统引入额外的时间统计函数** - 在`arch/x86/entry/syscalls/syscall_64.tbl`中注册个新的条目用于表示即将加入的服务项; - 更新头文件`include/linux/syscalls.h`声明原型以便其他组件引用; - 开发具体的业务逻辑位于`kernel/sys.c`之内实现期望的行为; - 构建整个项目结构并通过系列单元检验确认无误之后部署至真实环境中试用。 5. **验证成果的有效性** 设计专门的应用场景模拟真实的请求过程从而评估性能指标是否达到标准范围以内。 ```c // syscall_64.tbl 中增加行 335 64 sys_my_syscall __x64_sys_my_syscall // syscalls.h 添加声明 asmlinkage long sys_my_syscall(int pid); // sys.c 实现方法体 SYSCALL_DEFINE1(my_syscall, int, pid){ struct task_struct *task; unsigned long user_time, kernel_time; rcu_read_lock(); task = find_get_pid(pid); if (!task) { rcu_read_unlock(); return -ESRCH; /* No such process */ } getrusage(task, RUSAGE_BOTH, &ru); user_time = ru.ru_utime.tv_sec*HZ + ru.ru_utime.tv_usec/(1000000/HZ); kernel_time = ru.ru_stime.tv_sec*HZ + ru.ru_stime.tv_usec/(1000000/HZ); rcu_read_unlock(); // 将结果复制给用户空间缓冲区 copy_to_user(buf, (void*)&user_time, sizeof(unsigned long)); copy_to_user((char*)buf+sizeof(unsigned long), (void*)&kernel_time, sizeof(unsigned long)); return 0; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值